正则表达式懒惰量词断言开始和结束

时间:2015-01-24 05:49:59

标签: regex match lazy-evaluation regex-greedy

当将正则表达式量化为惰性时,例如\w{2,4}?,在断言作为测试的开始和结束时,它是否比其他(贪婪)效率更高或更低?

e.g。 ^\w{2,4}?$ vs ^\w{2,4}$测试' 12345' ' 1234'

2 个答案:

答案 0 :(得分:3)

两者都不匹配您的测试字符串,因为您的输入包含5个字符,其中正则表达式仅匹配具有2到4个字符的字符串。使用锚点时,不需要?^.*?$^.*$的作用相同。我建议您使用^\w{2,4}$代替^\w{2,4}?$。第二个步骤需要8个步骤来找到匹配,其中第一个将采取5个步骤来找到匹配。

DEMO

让我们将1234视为示例字符串。

  1. ^\w{2,4}$

    从一开始,上面的正则表达式将匹配所有字符,其中贪婪地包含2到4个字符,$锚点断言我们在最后。

  2. ^\w{2,4}?$

    但是当我们使用它时,它会匹配两个字符并检查该行的结尾。因为第二个字符旁边没有行锚点的末尾,所以它与第三个字符匹配,并再次检查第三个字符旁边的行锚点的结尾。结果为否,因此它移动到下一个字符并匹配它。现在它检查线锚的结束。是的,它已经结束了。如果第四个字符后面有任何字符,则丢弃它的操作。这是采取比贪婪步骤更多步骤的原因。

答案 1 :(得分:0)

<击> 不会。贪婪和懒惰的量词都会产生“回溯”。

但是,possessive quantifier "+"不会创建回溯,因此在某些情况下会更快。它确实有一个非常具体的行为,并且有许多正则表达式引擎不支持占有量词(javascript没有,PCRE会这样做)

作为Avinash Raj精神错误,此特定示例中不会使用回溯,以及所有这些表达式

^\w{2,5}?$ ^\w{2,5}$ ^\w{2,5}+$ ^\w{2,4}?$ ^\w{2,4}$ ^\w{2,4}+$

在匹配字符串12345的时间上没有区别

请参阅Avinash Raj's answer回答。

<?php header('Content-Type: text/plain');
$s = str_repeat("12345\n",1000);
function a($r){
    global $s;
    $r = '#'.$r.'#m';
    $time_a = (double)microtime(true);
    for($i=0;$i<100000;$i++)preg_match( $r, $s );
    echo "$r\t".( (double)microtime(true) - $time_a )."\n";
}
a('^\w{2,5}$');  // 0.093012094497681 ; 0.10101294517517 
a('^\w{2,5}?$'); // 0.095011949539185 ; 0.09201192855835 
a('^\w{2,5}+$'); // 0.094011783599854 ; 0.093512058258057
a('^\w{2,4}$');  // 4.3395512104034   ; 4.3435509204865    
a('^\w{2,4}?$'); // 4.3420507907867   ; 4.3610541820526    
a('^\w{2,4}+$'); // 4.3565537929535   ; 4.353052854538     
// lazy "?" quantifier is slower than greedy