c# - 如何修复 BBcode 正则表达式

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

我有一个抓取 BBcode 标签的正则表达式。除了一个小故障外,它工作得很好。

这是当前表达式:

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

这是它成功匹配的一些文本和它构建的组:

[url=http://www.google.com]Go to google![/url]
1: url
2: http://www.google.com
3: Go to google!

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

[quote][quote]first nested quote[/quote][quote]second nested quote[/quote][/quote]
1: quote
2: NULL
3: [quote]first nested quote[/quote][quote]second nested quote[/quote]

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

[quote]first nested quote[/quote][quote]second nested quote[/quote]
1: quote
2: NULL
3: first nested quote[/quote][quote]second nested quote

啊啊啊!那根本不是我们想要的。有一个相当简单的方法来修复它,我从这个修改正则表达式:

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

对此:

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

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

[quote]first nested quote[/quote][quote]second nested quote[/quote]

[quote]first nested quote[/quote]
1: quote
2: NULL
3: first nested quote

[quote]second nested quote[/quote]
1: quote
2: NULL 3: second nested quote

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

[quote][quote]first nested quote[/quote][quote]second nested quote[/quote][/quote]

[quote][quote]first nested quote[/quote]
1: quote
2: NULL
3: [quote]first nested quote

[quote]second nested quote[/quote]
1: quote
2: NULL
3: second nested quote

第一个匹配完全错误,第二个匹配虽然格式正确,但不是理想的匹配。我们想要一个大匹配,第三个匹配组是两个嵌套的引号标签,就像我们使用第一个表达式时一样。

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

最佳答案

使用 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)

关于c# - 如何修复 BBcode 正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7018321/

相关文章:

c# - 哈希表的通用版本是什么?

c# - 在代码而不是配置文件中将 Message Inspector 添加到 WCF 服务

python - Re.findall 仅返回 Python 2.7 中的第一个匹配项

java - 匹配非多行正则表达式

c# - SQL Server 存储过程提示缺少参数,但正在设置

c# - .net 中的 XML 序列化

c# - 如何在 jQuery 中调用 C# 方法?

c# - .NET - 在没有继承或 Postsharp 的情况下拦截对象

.net - Xamarin.Forms 和 .Net 标准 2.0

regex - 匹配奇数长度的字符串