处理Javascript正则表达式子匹配

处理Javascript正则表达式子匹配,javascript,regex,markdown,Javascript,Regex,Markdown,我试图编写一些JavaScript正则表达式,用真正的html标记替换用户输入的标记,因此[b]将变成等等。我使用的正则表达式看起来是这样的 var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig; 使用以下JavaScript s.replace(exptags,"<$1>$2</$1>"); 但是,如果标记嵌套在彼此内部,它将只匹配外部标记,例如 [b]foo [u]to the[/u

我试图编写一些JavaScript正则表达式,用真正的html标记替换用户输入的标记,因此
[b]
将变成
等等。我使用的正则表达式看起来是这样的

var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;
使用以下JavaScript

s.replace(exptags,"<$1>$2</$1>");
但是,如果标记嵌套在彼此内部,它将只匹配外部标记,例如

[b]foo [u]to the[/u] bar[/b]
这将仅与
b
标记匹配。我怎样才能解决这个问题?我应该循环直到起始字符串与结果相同吗?我有一种感觉,
(({1,}?
模式也错了


谢谢你不能用正则表达式表达递归

但是,您可以使用平衡匹配使用.NET的System.Text.RegularExpressions来实现这一点。请参阅此处的更多信息:

如果您使用的是.NET,您可能可以通过回调实现所需的功能。 如果没有,您可能需要使用自己的小javascript解析器

同样,如果您有能力访问服务器,您可以使用完整的解析器。:)


你要这个干什么?如果不是为了预览,我强烈建议您在服务器端进行处理。

AFAIK您不能用正则表达式表示递归

但是,您可以使用平衡匹配使用.NET的System.Text.RegularExpressions来实现这一点。请参阅此处的更多信息:

如果您使用的是.NET,您可能可以通过回调实现所需的功能。 如果没有,您可能需要使用自己的小javascript解析器

同样,如果您有能力访问服务器,您可以使用完整的解析器。:)


你要这个干什么?如果不是预览,我强烈建议您在服务器端进行处理。

是的,您必须循环。或者,由于您的标记看起来非常像HTML标记,您可以分别替换
[b]
,以及
[/b]
。(.){1,}? 与(.*)相同-即任何符号,最小可能的序列长度


更新:感谢MrP,(..{1,}?是(+.)+?,我的错。

是的,你必须循环。或者,由于您的标记看起来非常像HTML标记,您可以分别替换
[b]
,以及
[/b]
。(.){1,}? 与(.*)相同-即任何符号,最小可能的序列长度


更新:感谢MrP,(..{1,}?是(.)+?,我的错。

你说得对,内部模式很麻烦

((.){1,}?)
也就是说,至少进行一次捕获匹配,然后捕获整个过程。标记中的每个字符都将被捕获为一个组

当您不需要结束元素名时,您也在捕获它,并且在暗示结束元素名时使用
{1}
。以下是清理版本:

/\[(b|u|i|s|center|code)](.+?)\[\/\1]/ig

对另一个问题不确定。

您认为内部模式很麻烦,这是对的

((.){1,}?)
也就是说,至少进行一次捕获匹配,然后捕获整个过程。标记中的每个字符都将被捕获为一个组

当您不需要结束元素名时,您也在捕获它,并且在暗示结束元素名时使用
{1}
。以下是清理版本:

/\[(b|u|i|s|center|code)](.+?)\[\/\1]/ig

不确定另一个问题。

您可以重复应用regexp,直到它不再匹配。这会做一些奇怪的事情,比如“[b][b]foo[/b][b]”=>“[b]foo[/b]”=>“foo”,但就我所见,最终结果仍然是一个带有匹配(尽管不一定正确嵌套)标记的合理字符串


或者,如果您想做到“正确”,只需编写一个简单的递归下降解析器。尽管人们可能希望“[b]foo[u]bar[/b]baz[/u]”能够工作,但这很难用解析器识别。

您可以重复应用regexp,直到它不再匹配为止。这会做一些奇怪的事情,比如“[b][b]foo[/b][b]”=>“[b]foo[/b]”=>“foo”,但就我所见,最终结果仍然是一个带有匹配(尽管不一定正确嵌套)标记的合理字符串


或者,如果您想做到“正确”,只需编写一个简单的递归下降解析器。尽管人们可能期望“[b]foo[u]bar[/b]baz[/u]”起作用,但这很难用解析器来识别。

嵌套块没有被替换的原因是因为[b]的匹配将位置放在[/b]之后。因此,(..{1,}?)匹配的所有内容都将被忽略

可以在服务器端编写递归解析器——Perl使用,Ruby可能也有类似的功能

不过,您不一定需要真正的递归。您可以使用相对简单的循环来等效地处理字符串:

var s = '[b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]';
var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;

while (s.match(exptags)) {
   s = s.replace(exptags, "<$1>$2</$1>");
}

document.writeln('<div>' + s + '</div>'); // after
  • {1} 当不存在其他计数说明符时,假定为
  • {1,}可以缩短为+

嵌套块未被替换的原因是[b]的匹配将位置放在[/b]之后。因此,(..{1,}?)匹配的所有内容都将被忽略

可以在服务器端编写递归解析器——Perl使用,Ruby可能也有类似的功能

不过,您不一定需要真正的递归。您可以使用相对简单的循环来等效地处理字符串:

var s = '[b]hello[/b] [u]world[/u] [b]foo [u]to the[/u] bar[/b]';
var exptags = /\[(b|u|i|s|center|code){1}]((.){1,}?)\[\/(\1){1}]/ig;

while (s.match(exptags)) {
   s = s.replace(exptags, "<$1>$2</$1>");
}

document.writeln('<div>' + s + '</div>'); // after
  • {1} 当不存在其他计数说明符时,假定为
  • {1,}可以缩短为+

    • 同意Richard Szalay的观点,但他的正则表达式没有被正确引用:

      var exptags = /\[(b|u|i|s|center|code)](.*)\[\/\1]/ig;
      
      它更干净。请注意,我还将
      +?
      更改为
      *
      +?
      有两个问题:

    • 您将无法匹配[u][/u],因为它们之间至少没有一个字符(+)
    • 非贪婪匹配不会很好地处理嵌套在其内部的相同标记(?)

    • 同意Richard Szalay的观点,但他的正则表达式没有被正确引用:

      var exptags = /\[(b|u|i|s|center|code)](.*)\[\/\1]/ig;
      
      它更干净。请注意,我还将
      +?
      更改为
      *
      +?
      有两个问题:

    • 您将无法匹配[u][/u],因为它们之间至少没有一个字符(+)
    • 一个不贪婪的对手不会很好地处理同一个ta
      <b><i>helloworld</i></b>
      <b>helloworld</b>
      
      var tagreg = /\[(\/?)(b|u|i|s|center|code)]/ig
      div.innerHTML="[b][i]helloworld[/b]".replace(tagreg, "<$1$2>") //no closing i
      //div.inerHTML=="<b><i>helloworld</i></b>"