正则表达式负面向前看以匹配降价链接

时间:2017-10-20 13:03:29

标签: .net regex regex-lookarounds

我们遇到了正则表达式问题。

这是问题所在。考虑以下两种模式:

1)[hello] [world]

2)[hello [world]]

我们需要编写一个正则表达式,只能匹配第一个中的[world]和第二个中的整个模式([hello [world]])。

通过使用负向前瞻,我编写了以下正则表达式来解决部分问题:

\[[^\[\]]+\](?!.*\[[^\[\]]+\])

这个正则表达式符合我们想要的模式1),但不适用于模式2)。

3 个答案:

答案 0 :(得分:2)

在.NET正则表达式中,您可以使用平衡组来匹配嵌套的平衡括号。因此,要在一行上匹配最后一个[...]子字符串(带有嵌套括号),您需要一个很长的模式,如

\[(?:[^][]+|(?<c>)\[|(?<-c>)])*(?(c)(?!))](?!.*\[(?:[^][]+|(?<d>)\[|(?<-d>)])*(?(d)(?!))])

请参阅regex demo at RegexStorm.net

<强>详情

  • \[(?:[^][]+|(?<c>)\[|(?<-c>)])*(?(c)(?!))] - 带有嵌套括号的[...]子字符串:
    • \[ - [字符
    • (?:[^][]+|(?<c>)\[|(?<-c>)])* - 零次或多次出现:
      • [^][]+| - 除][
      • 以外的1个或多个字符
      • (?<c>)\[| - 将空值添加到群组&#34; c&#34;和[匹配
      • (?<-c>)] - 从组&#34; c&#34;中减去空值堆栈与]匹配
    • (?(c)(?!)) - 如果Group&#34; c&#34;堆栈不是空的
    • ] - ]字符
  • (?!.*\[(?:[^][]+|(?<d>)\[|(?<-d>)])*(?(d)(?!))]) - 除了换行符号之外没有跟随任何0+字符,后面跟上面的字符相同。

答案 1 :(得分:0)

这里有另一种可能的解决方案来匹配所有降价链接,如果&#34;正确&#34;逃脱了。

这里是正则表达式:

\[(?<text>(?:[^\[\]]|\\\[|\\\])+?)\]\((?<link>.+?)\)

请参阅regex 101 demo

请注意,这不支持链接内的NOT转义括号:

[link number \[2]](http://myurl.com)
[link number [2\]](http://myurl.com)

它也可能不支持其他边缘情况......

答案 2 :(得分:0)

使用.net正则表达式引擎在字符串中查找最后一个平衡方括号部分的更简单方法是使用Regex.RightToLeft属性从右到左搜索字符串。这样你就可以避免:

  • 搜索所有字符串
  • 用前瞻检查字符串的结尾,因为模式返回右边的第一个匹配。

代码:

string input = @"[hello] [world] [hello [world\]] ]";
string rtlPattern = @"(?(c)(?!))\[(?>\\.|(?<!\\)[^][]+|(?<-c>)\[|(?<c>)])*]";
Match m;

m = Regex.Match(input, rtlPattern, RegexOptions.RightToLeft);

if (m.Success)
    Console.WriteLine("Result: {0}", m.Groups[0].Value);

demo

请注意,为了更好地理解会发生什么,您还需要从右到左阅读模式的某些部分。详细说明:

]  # a literal closing square bracket

(?> # open an atomic group (*)
    \\.         # any escaped character with a backslash
  |
    [^][]+  # all that isn't a square bracket
    (?<!\\) # not preceded by a backslash
  |
    (?<-c>) \[  # decrement the c stack for an opening bracket
  |
    (?<c>)   ]  # increment the c stack for a closing bracket
)* # repeat zero or more times

\[  # a literal square opening bracket

(?(c) # conditional statement: true if c isn't empty
    (?!) # always failing pattern: "not followed by nothing"
)

(*)请注意,此处必须使用原子组以避免最终的灾难性回溯,因为该组包含具有+量词的项目并且本身会重复。您可以详细了解此问题here

此模式已经处理了转义嵌套括号,如果要匹配包含换行符的部分,还可以添加Regex.Singleline属性。