【问题标题】:C# regexp for nested tags用于嵌套标签的 C# 正则表达式
【发布时间】:2011-06-12 20:42:38
【问题描述】:

让我们从一个小例子开始;我有以下文字:

[[一些标签[[带有嵌套标签]]和再次]]

我想匹配 [[ with tag nested ]] 但不匹配 [[ some tag [[ with tag nested ]] 。简单

\[\[(?<content>.+?)\]\]

显然没有用。所以我创建了正则表达式:

\[\[(?!.*?\[\[.*?\]\].*?)(?<content>.+?)\]\]

不幸的是,它不匹配任何使用 C#(使用 MatchOptions.SingleLine)的东西,而 PHP 的 preg_match 可以完美运行。

任何线索/想法?任何帮助将不胜感激。

【问题讨论】:

  • 我在 C# 中使用 SingleLine 选项运行你的正则表达式没有问题。它正确返回 [[ with tag nested ]]。你能发布你的代码吗?
  • 我不确定我是否看到了问题。我使用您的第二个模式和RegexOptions.Singleline 创建了一个System.Text.RegularExpressions.Regex,然后在您的示例字符串上调用Match。它返回了一次捕获“[[ with tag nested ]]”。
  • @Harry:试试这个输入:[[ outer1 [[ nested1 ]] outer2 [[ nested2 ]] outer3 ]]。如果我正确理解了这个问题,它应该匹配nested1nested2,但它只匹配nested2
  • 很抱歉造成混淆,但我简化了示例,以便更容易理解预期的结果。令人惊讶的是,提供的示例成功地使用了正则表达式......但不是真正的主题。 Alan 是对的,我想匹配所有嵌套标签。感谢大家花时间提供帮助。

标签: c# regex nested regex-negation


【解决方案1】:

我知道找到最里面的一个括号的最简单方法是:

var match = Regex.Match(input, @"^.*(\[\[(.*?)\]\])", RegexOptions.Singleline);

这是有效的,因为它找到了 last [[(因此在它之后没有更多的 [[,因此它不能包含任何嵌套标签),然后是紧随其后的 ]] .当然,这是假设格式良好;如果你有一个字符串的开始/结束括号不正确匹配,这可能会失败。

找到最里面的括号后,您可以将其从输入字符串中删除:

input = input.Remove(match.Groups[1].Index, match.Groups[1].Length);

然后在while循环中重复这个过程,直到正则表达式不再匹配。

【讨论】:

  • 恐怕这不会产生我(你可能)想要的:它从第一个 [[ 匹配。无论如何,感谢您的回复。
  • @Avaer:不,它没有。它工作得很好。你试过了吗?如果您认为它失败了,请提供一个失败的示例输入。
  • 欠你一个道歉,我没有观察Groups[1]的内容,只是匆忙检查了Value。它确实有效。再次感谢。
【解决方案2】:

这是一个有效的匹配吗?

[[ with [ single ] brackets ]]

如果不是,这个正则表达式应该这样做:

 \[\[(?<content>[^][]*)\]\]

[^][] 匹配任何不是[] 的字符。如果允许单括号,试试这个:

\[\[(?<content>(?:(?!\[\[|\]\]).)*)\]\]

(?!\[\[|\]\]). 匹配任何字符,但必须确保它不是[[]] 序列的开头。

【讨论】:

  • @Avaer:我的也是,而且我的更简单。
  • @Timwi,我更喜欢 Alan 的建议。从正则表达式较短的意义上说,也许您的更简单,但是弄清楚它为什么起作用(因为第一个 .* 消耗了整行,然后回溯到最后一个 [[)并不是那么直观。此外,您的提议不处理 aaa [[ bbb ccc ]] [[ ddd 之类的情况。
  • @Bert:您给出的示例由我的正则表达式处理得很好。你试过了吗? — 另外,我很高兴您认为这里的这个更容易弄清楚;相比之下就很可怕了:)
  • @Timwi:试试我在另一条评论中使用的示例:[[outer1[[nested1]]outer2[[nested2]]outer3]]。使用Matches() 方法,您的正则表达式仅捕获nested2,而我的正则表达式根据需要捕获nested1nested2。我同意这很可怕,但它尽可能简单并且仍然满足要求。
  • @Alan:正如我在回答中提到的,它只找到最里面的一个括号,如果你想匹配所有这些,你总是可以使用一段时间环形。我想不出一个合理的用例,在这种用例中,您只需要最里面的括号而所有括号都,所以在99%的情况下,您的Matches接近仍然需要一个while循环。