我有一个抓住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表达式。
答案 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]