regex - 正则表达式 ‘(?<=#)[^#]+(?=#)’如何工作?

标签 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>用于命名组,但是在这种情况下,尖括号永远不会关闭。

我在文档中找不到?=,搜索起来确实很困难,因为搜索引擎通常会忽略那些特殊字符。

最佳答案

它们称为环顾四周;它们允许您断言某个模式是否匹配,而无需实际进行匹配。有4种基本的解决方法:

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

  • 作为一个简单的提醒,请环顾一下:
  • =为正,!为负
  • <在后面,否则向前看

  • 引用文献
  • regular-expressions.info/Lookarounds


  • 但是为什么要使用环顾四周?

    有人可能会争辩说,不需要在上述模式中环顾四周,并且#([^#]+)#可以很好地完成工作(提取\1捕获的字符串以获取non-#)。

    不完全的。区别在于,由于环视与#不匹配,因此下次尝试查找匹配项时,它可以再次“使用”。简单地说,环顾四周允许“匹配项”重叠。

    考虑以下输入字符串:
    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上得到证明,因为它不支持向后看。但是,它确实支持先行,因此我们可以对#([a-z]+)(?=#)进行类似的操作,该匹配项(as seen on rubular.com):
    and #one# and #two# and #three#four#
        \__/      \__/      \____/\___/
    

    引用文献
  • regular-expressions.info/Flavor Comparison
  • 关于regex - 正则表达式 ‘(?<=#)[^#]+(?=#)’如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3092797/

    相关文章:

    Python 3.5 目录的正则表达式匹配

    php - 计算开始的空格

    javascript - 在此新 RegExp 的上下文中,.source 的功能是什么

    regex - 在最后一次出现 '- ' 或 '|' 后截断字符串

    ios - 正则表达式非常适合主题标签和@usernames 但不适用于 URL

    c# - 正则表达式同时向前看和向后看

    C# - 负先行似乎不起作用

    php - 正则表达式:向后看以避免出现奇数个连续反斜杠

    python - 使用正则表达式查找括号之间的特定字符串(包括括号)

    javascript - js正则表达式转义引号