懒惰量词在这个特定的正则表达式中有什么不同?

时间:2014-02-15 17:56:59

标签: regex perl

我正在阅读关于正则表达式的具体示例/练习 要处理的句子是:

<b>Billions</b> and <b>Zillions</b> of suns   

所需的匹配是Billions,即<b></b>之间的文字 该解决方案提出了2个正则表达式:
第一:

<b>((?!<b>).)*?</b>   

我不明白为什么这里需要懒惰的量词。在我看来,这是多余的 然后第二个解决方案提出以下内容,以便能够删除惰性限定符:
第二:

<b>((?!</?b>).)*?</b>   

我能理解第二种解决方案,但对我而言,解决与懒惰有关的任何问题似乎都是无关紧要的。我的意思是:

<b>((?!<b>).)*</b>   

据我所知,它会匹配Billions就好了。它将贪婪地达到Zillions的<b>,然后它将开始回溯直到达到Billions的</b>并达到匹配。

示例:

$ perl -e '  
my $var = "<b>Billions</b> and <b>Zillions</b> of suns";  
$var =~ /<b>(((?!<b>).)*)<\/b>/;print "$1\n";  
'  
Billions  

我在这里误解了什么吗? 可能是作者试图编写一个对所有工具都有效的正则表达式吗?

1 个答案:

答案 0 :(得分:0)

<b>((?!<b>).)*?</b><b>((?!<b>).)*</b>之间的区别仅在于性能和所涉及的回溯量。

第一个正则表达式将与您的示例句中的Billions匹配并停在那里。

第二个正则表达式将匹配Billions and ,然后在找到匹配项之前开始回溯。因此第二个效率降低。但是如果你再看一遍,如果没有嵌套标签(例如<b>.*?</b>,那么如果包含要回溯的字符数,则正则表达式在匹配的字符数方面也可以相当于<b>Billions and <b>Zillions</b></b> of suns。但这很愚蠢,因为嵌套的<b>不会改变格式。)

我自己会用:

<b>((?!</b>).)*</b>

作为正则表达式。否定前瞻中的</b>会阻止</b>的匹配,最终比第一个正则表达式更有效。

例如,您可以看到在获得以下匹配项之前所采取的“步骤”数量: