正则表达式正向前瞻 - 总是失败的模式

时间:2013-08-28 08:03:15

标签: regex lookahead

我正在学习正则表达式,我找到了以下模式:

q(?=u)i

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

我没有看到任何符合此模式的词。有什么案子吗?或者这种结构(模式 - 前瞻 - 模式的其余部分)是否有用?

4 个答案:

答案 0 :(得分:3)

正则表达式的外观语法为zero width

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

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

请注意,模式不会回溯,外观断言为零宽度。

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

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

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

答案 1 :(得分:2)

不,没有类似于我所见过的匹配模式,但是可以使用这样的结构(尽管有点奇怪),例如:

q(?=.*t)u

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

答案 2 :(得分:1)

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

foo(?=bar)fixed

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

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

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

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

答案 3 :(得分:0)

在应用此问题中提出的用例结构和Boris the Spider的响应时,我想出了这个解决方案

$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](?=.*(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\2>))[/q]*应用于上述详细信息; \[q]匹配[q],代码的html部分与(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\2>))匹配。

前瞻的匹配被丢弃,因此引擎从字符串中的[/ q]返回到代码的html部分。前瞻是成功的,因此引擎继续[/q]。但[/q]无法匹配(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\2>))。所以这场比赛尝试失败了。

然而,这个正则表达式合成器有效:

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

正则表达式引擎只是说:&#34;打开[code]标记后跟任何字符,然后是一对html标记,最后至少有一个结束[/code]标记&#34;。< / p>

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