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

时间:2010-06-22 11:55:53

标签: regex lookahead lookbehind lookaround

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

(?<=#)[^#]+(?=#)

我会将其分解为我认为理解的内容:

(?<=#)    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 `?=`?

所以我遇到的问题是?<=?<部分。从阅读MSDN开始,?<name>用于命名组,但在这种情况下,尖括号永远不会关闭。

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

3 个答案:

答案 0 :(得分:33)

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

  • 正面看法:看看我们是否可以匹配pattern ...
    • (?=pattern) - ...到当前位置的(看提前
    • (?<=pattern) - ...到当前位置的(看后面)
  • 否定的外观 - 看看我们是否与pattern不匹配
    • (?!pattern) - ... right
    • (?<!pattern) - ...到 left

简单提醒一下:

  • = 肯定! 否定
  • <看起来后面,否则看起来提前

参考


但为什么要使用外观?

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

不完全。区别在于,由于环视不会匹配 #,因此可以在下次尝试查找匹配时再次“使用”它。简单来说,lookarounds允许“匹配”重叠。

考虑以下输入字符串:

and #one# and #two# and #three#four#

现在,#([a-z]+)#将提供以下匹配项(as seen on rubular.com):

and #one# and #two# and #three#four#
    \___/     \___/     \_____/

将此与(?<=#)[a-z]+(?=#)进行比较,匹配:

and #one# and #two# and #three#four#
     \_/       \_/       \___/ \__/

不幸的是,这不能在rubular.com上展示,因为它不支持lookbehind。但是,它确实支持前瞻,因此我们可以使用匹配(as seen on rubular.com)的#([a-z]+)(?=#)执行类似操作:

and #one# and #two# and #three#four#
    \__/      \__/      \____/\___/

参考

答案 1 :(得分:4)

正如另一张海报所提到的,这些是 lookarounds ,这是用于更改匹配内容以及何时更改内容的特殊构造。这说:

(?<=#)    match but don't capture, the string `#`
            when followed by the next expression

[^#]+     one or more characters that are not `#`, and

(?=#)     match but don't capture, the string `#`
            when preceded by the last expression

因此,这将匹配两个#之间的所有字符。

在许多情况下,前瞻和外观非常有用。例如,请考虑“匹配所有b未遵循a”的规则。您的第一次尝试可能类似于b[^a],但这不对:这也会与bu中的busbo中的boy相匹配,但是您只想要b。它与b中的cab不匹配,即使后面没有a,因为没有其他字符可供匹配。

要做到这一点,你需要一个前瞻:b(?!a)。这表示“匹配b但之后与a不匹配,并且不会使匹配成为该部分”。因此它只匹配b中的bolo,这就是你想要的;同样,它会匹配b中的cab

答案 2 :(得分:1)

他们被称为 look-arounds http://www.regular-expressions.info/lookaround.html