正则表达式'(?<=#)[^#] +(?=#)'如何工作?

kni*_*ttl 20 regex lookahead lookbehind lookaround

我在C#程序中有以下正则表达式,并且难以理解它:

(?<=#)[^#]+(?=#)
Run Code Online (Sandbox Code Playgroud)

我会把它分解为我认为我理解的内容:

(?<=#)    a group, matching a hash. what's `?<=`?
[^#]+     one or more non-hashes (used to achieve non-greediness)
(?=#)     another group, matching a hash. what's the `?=`?
Run Code Online (Sandbox Code Playgroud)

所以这个问题我已经是?<=?<组成部分.从阅读MSDN,?<name>用于命名组,但在这种情况下,尖括号永远不会关闭.

?=在文档中找不到,搜索它真的很难,因为搜索引擎大多会忽略那些特殊的字符.

pol*_*nts 33

它们被称为外观; 它们允许您断言模式是否匹配,而不实际进行匹配.有4种基本的外观:

  • 积极的外观:看看我们是否可以匹配pattern......
    • (?=pattern)- ......在当前位置右侧(向前看)
    • (?<=pattern)- ...在当前位置的左侧(向后看)
  • 否定的外观 - 看看我们是否无法匹配 pattern
    • (?!pattern)- ......在右边
    • (?<!pattern)- ......在左边

作为一个简单的提醒,一个看起来:

  • =积极的,!消极的
  • <看起来是后面,否则它是向前看

参考


但为什么要使用外观?

有人可能会争辩说上面模式中的外观并不是必需的,并且#([^#]+)#可以很好地完成工作(提取捕获的字符串\1以获取非#).

不完全的.不同的是,因为环视不匹配#,可以"拿来主义"再次下一次尝试找到一个匹配.简单地说,lookarounds允许"匹配"重叠.

考虑以下输入字符串:

and #one# and #two# and #three#four#
Run Code Online (Sandbox Code Playgroud)

现在,#([a-z]+)#将给出以下匹配(如rubular.com上所示):

and #one# and #two# and #three#four#
    \___/     \___/     \_____/
Run Code Online (Sandbox Code Playgroud)

比较一下(?<=#)[a-z]+(?=#),匹配:

and #one# and #two# and #three#four#
     \_/       \_/       \___/ \__/
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不能在rubular.com上展示,因为它不支持lookbehind.但是,它确实支持前瞻,所以我们可以做类似的事情#([a-z]+)(?=#),匹配(如rubular.com上所见):

and #one# and #two# and #three#four#
    \__/      \__/      \____/\___/
Run Code Online (Sandbox Code Playgroud)

参考