如何修复BBcode正则表达式

时间:2011-08-10 21:52:41

标签: c# .net regex regex-negation recursive-regex

我有一个抓住BBcode标签的正则表达式。除了小故障外,它的效果很好。

这是当前表达式:

\[([^=\[\]]+)[=\x22']*([^ \[\]]*)['\x22]*\](.+)\[/\1\]

以下是它成功匹配的一些文本及其构建的组:

  

[url = http://www.google.com]Go google![/ url]
  1:网址
  2:http://www.google.com
  3:去谷歌!

     

[IMG] http://www.somesite.com/someimage.jpg[/img]
  1:img
  2:NULL
  3:http://www.somesite.com/someimage.jpg

      [quote] [quote]第一次嵌套引用[/ quote] [quote]第二次嵌套引用[/ quote] [/ quote]
  1:报价
  2:NULL
  3:[quote]第一个嵌套引用[/ quote] [quote]第二个嵌套引用[/ quote]

所有这一切都很棒。我可以通过对同一个正则表达式运行第三个匹配组来处理嵌套标记,并递归处理嵌套的所有标记。问题在于使用[quote]标签的示例。请注意,第三个匹配组是一组两个引用标记,因此我们期望两个匹配。但是,我们得到一个匹配,如下:

  

[quote]第一次嵌套引用[/ quote] [quote]第二次嵌套引用[/ quote]
  1:报价
  2:NULL
  3:第一次嵌套引用[/ quote] [quote]第二次嵌套引用

AHHHH!这根本不是我们想要的。有一种相当简单的方法来解决它,我修改了正则表达式:

\[([^=\[\]]+)[=\x22']*([^ \[\]]*)['\x22]*\](.+)\[/\1\]

对此:

\[([^=\[\]]+)[=\x22']*([^ \[\]]*)['\x22]*\](((?!\[/\1\]).)+)\[/\1\]

如果第三个匹配组包含结束的BBcode标记,则添加((?!\[/\1\]).)我们会使整个匹配无效。所以现在这个工作,我们得到两个匹配:

  

[quote]第一个嵌套引用[/ quote] [quote]第二个嵌套引用[/ quote]

     

[quote]第一次嵌套引用[/ quote]
  1:报价
  2:NULL
  3:第一个嵌套引用

     

[quote]第二次嵌套引用[/ quote]
  1:报价
  2:NULL   3:第二次嵌套引用

我很高兴修复它,但现在我们还有另一个问题。这个新的正则表达式在第一个上面失败,我们将两个引用标记嵌套在一个较大的引用标记下。我们得到两个匹配而不是一个:

  

[quote] [quote]第一次嵌套引用[/ quote] [quote]第二次嵌套引用[/ quote] [/ quote]

      [quote] [quote]首先嵌套引用[/ quote]
  1:报价
  2:NULL
  3:[quote]第一个嵌套引用

     

[quote]第二次嵌套引用[/ quote]
  1:报价
  2:NULL
  3:第二次嵌套引用

第一场比赛全是错误的,第二场比赛虽然格局合理,但不是理想的比赛。我们希望与第三个匹配组的一个大匹配是两个嵌套的引用标记,就像我们使用第一个表达式时一样。

有什么建议吗?如果我能跨越这个差距,我应该有一个相当强大的BBcode表达式。

1 个答案:

答案 0 :(得分:4)

使用balancing groups你可以构造一个这样的正则表达式:

(?>
  \[ (?<tag>[^][/=\s]+) \s*
  (?: = \s* (?<val>[^][]*) \s*)?
  ]
)

(?<content>
  (?>
    \[(?<innertag>[^][/=\s]+)[^][]*]
    |
    \[/(?<-innertag>\k<innertag>)]
    |
    [^][]+
  )*
  (?(innertag)(?!))
)

\[/\k<tag>]

根据Kobi的例子简化。


以下内容:

[foo=bar]baz[/foo]
[b]foo[/b]
[i][i][foo=bar]baz[/foo]foo[/i][/i]
[i][i][i][i]foo[/i][/i][/i][i][i]foo[/i][/i][/i]
[quote][quote][b][img]foo[/img][b]bold[/b][b][b]deep[/b][/b][/b][/quote]bar[quote]baz[/quote][/quote]

找到这些匹配:

  • [foo=bar]baz[/foo]
  • [b]foo[/b]
  • [i][i][foo=bar]baz[/foo]foo[/i][/i]
  • [i][i][i][i]foo[/i][/i][/i][i][i]foo[/i][/i][/i]
  • [quote][quote][b][img]foo[/img][b]bold[/b][b][b]deep[/b][/b][/b][/quote]bar[quote]baz[/quote][/quote]

http://ideone.com/uULOs

的完整示例

(旧版本http://ideone.com/AXzxW