【问题标题】:Finding two open brackets missing two closing brackets找到两个左括号缺少两个右括号
【发布时间】:2016-06-08 20:27:44
【问题描述】:

我想要一个正则表达式,它可以匹配任何以两个开括号开头但没有两个匹配的右括号的单词。例如:

Good afternoon Mr. [[Insured.InsuredName]] - Your policy 
[[Insured.CurrentPolicy is out of date.

在这种情况下,“Insured.CurrentPolicy”将被捕获。我是前瞻/后视的新手。感谢您的帮助。

【问题讨论】:

  • 这里不需要环顾四周。只需使用 \[\[([^]]*)]] 并获取 Group 1 值。
  • 匹配是否只包含左括号后的单词?
  • 嗯,非常好的谜题。如果您能对您尝试匹配的这些字符串可能包含的内容有所了解,那将会有所帮助。我建议使用字母匹配模式,但我也注意到,\w 可以用来代替 \p{L} 字母匹配模式,以防它们也可能包含数字和下划线。

标签: c# regex regex-lookarounds


【解决方案1】:

你可以试试

\[\[(?>(\p{Lu}\p{L}*(?:\.\p{Lu}\p{L}*)*))(?!]])

regex demo

解释

  • \[\[ - 两个 [ 符号
  • (?> - 一个原子组的开始,它将防止回溯到其子模式,因此如果在匹配失败后的前瞻,整个正则表达式可能会返回不匹配
  • (\p{Lu}\p{L}*(?:\.\p{Lu}\p{L}*)*) - 第 1 组捕获
    • \p{Lu}\p{L}* - 大写字母后跟 0+ 任意字母(注意:将 \p{L}* 替换为 \w* 以匹配字母数字和下划线字符)
    • (?:\.\p{Lu}\p{L}*)* - 零个或多个点序列,后跟一个大写字母,后跟 0+ 个任意字母(适用与上述相同的注释)。
  • ) - 原子组的结尾。
  • (?!]]) - 如果在匹配的文本之后有两个连续的 ]],则会导致匹配失败。

如果您只需要匹配[[之后的任何非空白和非]字符,您可以使用4castle's approach并使用

\[\[(?>([^]\s]+))(?!]])

this regex demo

其解释非常相似,只是[^]\s]+ 匹配除] 和空格之外的1 个或多个字符。

C#代码:

var results = Regex.Matches(input, @"\[\[(?>(\p{Lu}\p{L}*(?:\.\p{Lu}\p{L}*)*))(?!]])")
       .Cast<Match>()
       .Select(m => m.Groups[1].Value)
       .ToList();

【讨论】:

  • 我认为您误读了这个问题。它正在寻找 具有匹配右括号的左括号。
  • @4castle:我已经修改了答案以解决实际问题。
  • 输出中仍然包含误报。您可能需要一个原子组来防止回溯。
  • 那么,第一个应该不匹配吧?这个问题听起来相当模糊,但是是的,原子组在这里会很方便。我更新了答案以反映该要求。
  • 现在看起来不错 :) 作为参考,here's the PCRE regex I made 非常相似。 (我对 C# 正则表达式的风格不太熟悉,因此我没有自己回答)。
【解决方案2】:

你也可以试试这个,我在 Wiktor 的语法上遇到了一些错误。可能特定于某个版本的正则表达式。这似乎对大多数正则表达式版本都很灵活。

(\[\[\s*[a-zA-Z]+\.[a-zA-Z]+\b)(?!]])

Regex Example

【讨论】:

    【解决方案3】:

    在正则表达式中,“not”通常是你的敌人,所以对于这种情况,我建议只使用:

    \[\[[a-zA-Z.]+\]?([^a-zA-Z.\]]|$)
    

    它会遗漏一些像“[[Foo.Bar]Baz”这样的情况,但它的可读性很强,可以捕捉到很多情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多