代码之家  ›  专栏  ›  技术社区  ›  knittl

正则表达式如何?[^=α] [^α] +?=α)工作?

  •  20
  • knittl  · 技术社区  · 14 年前

    我在C程序中有以下regex,并且很难理解它:

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

    我将把它分解成我认为我理解的:

    (?<=#)    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 回复  |  直到 14 年前
        1
  •  33
  •   polygenelubricants    14 年前

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

    • 正面观察:看看我们是否能匹配 pattern
      • (?=pattern) -…到 正确的 当前位置(看 向前地 )
      • (?<=pattern) -…到 左边 当前位置(看 后面 )
    • 负面观察-看看我们是否无法匹配 模式
      • (?!pattern) -…到 正确的
      • (?<!pattern) -…到 左边

    作为一个简单的提醒,对于环顾四周:

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

    工具书类


    但是为什么要使用环视功能呢?

    有人可能会说,不需要在上面的模式中进行观察,并且 #([^#]+)# 会做得很好(提取 \1 获得非 # )

    不完全是这样。不同的是,因为环顾四周 比赛 这个 γ 下一次尝试查找匹配项时可以再次“使用”。简单地说,寻找允许“匹配”重叠。

    考虑以下输入字符串:

    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上演示,因为它不支持lookback。但是,它确实支持展望,因此我们可以用 #([a-z]+)(?=#) ,哪个匹配( as seen on rubular.com ):

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

    工具书类

        2
  •  4
  •   John Feminella    14 年前

    正如另一张海报所提到的,这些是 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
    

    所以这将匹配两个字符之间的所有字符 # S.

    lookaheads和lookbehinds在许多情况下非常有用。例如,考虑规则“全部匹配” b 后面不是 a “你的第一次尝试可能是 b[^a] 但这是不对的:这也将与 bu 在里面 bus bo 在里面 boy 但是你只想要 . 它不符合 在里面 cab 即使后面没有 ,因为没有其他要匹配的字符。

    要正确做到这一点,您需要有一个前瞻性: b(?!a) . 上面写着“匹配A” 但不匹配 然后,不要把那部分比赛变成比赛的一部分。因此,它将只匹配 在里面 bolo ,这是您想要的;同样,它将匹配 在里面 驾驶室 .

        3
  •  1
  •   Bart Kiers    14 年前