【问题标题】:Regex positive lookahead - pattern that always fails正则表达式积极前瞻 - 总是失败的模式
【发布时间】:2013-08-28 08:03:14
【问题描述】:

我正在学习正则表达式,我发现了以下模式:

q(?=u)i

如果我尝试计算 quit,它会失败,因为 q 匹配 q,u 匹配 u(所以前瞻是有效的),但是正则表达式在单词 quit 中回溯并且再次比较字符 u,这次和我一起。匹配失败。

我没有看到任何与此模式匹配的单词。有没有案例?或者这种结构(模式 - 前瞻 - 模式的其余部分)有用吗?

【问题讨论】:

    标签: regex lookahead


    【解决方案1】:

    正则表达式环视语法是zero width

    这意味着它匹配但不移动光标,所以在你的模式中:

    • q匹配“q”光标移动到“u”
    • (?=u)匹配“u”光标停留在“u”
    • i 与“u”不匹配,因此模式失败。

    请注意,模式不会回溯,环视断言的宽度为零。

    这个结构非常有用,如果你想匹配一个模式,比如在一系列字母中包含“至少一个 X”。例如:

    [a-z]{4}[1-9]{3}(?=.*X)[a-zA-Z]{5}
    

    表示四个小写字母,后跟三个数字,后跟五个任意大小写字母,至少有一个“X”。

    【讨论】:

      【解决方案2】:

      不,没有与你提到的我见过的类似的匹配模式,但是可以使用这样的结构(虽然有点奇怪),例如:

      q(?=.*t)u
      

      这个正则表达式将匹配任何以qu 开头但后面有t 的字符串。这意味着questionquit 将匹配,但quasar 不匹配。在这种情况下,可以使用等效且更易读的 (imo) 正则表达式 qu(?=.*t)

      【讨论】:

        【解决方案3】:

        我会说,如果先行 ((?=...)) 之后(或之前)的模式是固定的。正则表达式并没有多大意义。喜欢:

        foo(?=bar)fixed
        

        但如果fixed 部分是动态的,它会很有用。看这个例子:

        kent$  echo "fooququuuxxxxxxx"|grep -Po 'q(?=uu).*' 
        quuuxxxxxxx
        
        kent$  echo "fooququuuxxxxxxx"|grep -Po 'q(?=u).*' 
        ququuuxxxxxxx
        

        在上面的例子中,只有前瞻不同,你得到的匹配结果不同。

        【讨论】:

          【解决方案4】:

          在应用这个问题中提出的用例结构和蜘蛛鲍里斯的回答时,我想出了这个解决方案

          $detail = '[code]<!doctype>
          <html>
            <head></head>
            <body><p>My Regex script</p></body>
          </html>[/code]';
          
          function regex($detail) 
          {
             if(preg_match('#^\[code](?=.*(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\2>))\[/code]#si',  $detail))
             {
                 return true;
             }
             return false;        
          }
          echo regex($detail);
          

          看一下正则表达式引擎,这就是正在发生的事情。在将^\[q](?=.*(&lt;([A-Z][A-Z0-9]*)\b[^&gt;]*&gt;(.*?)&lt;/\2&gt;))[/q]* 应用于上面的 $detail 时; \[q] 匹配 [q] 并且代码的 html 部分匹配 (&lt;([A-Z][A-Z0-9]*)\b[^&gt;]*&gt;(.*?)&lt;/\2&gt;))

          前瞻中的匹配被丢弃,因此引擎从字符串中的 [/q] 退回到代码的 html 部分。前瞻成功,因此引擎继续使用[/q]。但是[/q] 不能匹配(&lt;([A-Z][A-Z0-9]*)\b[^&gt;]*&gt;(.*?)&lt;/\2&gt;))。所以这个匹配尝试失败了。

          但是这个正则表达式合成器可以工作:

          #^\[code](?=.*(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\2>\[/code]))#si
          

          正则表达式引擎简单地说:“打开[code]标签后跟任何字符,然后是一对html标签,最后至少有一个关闭[/code]标签”。

          我希望这有助于更多地解释用例模式匹配(退出)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-08-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多