正则表达式中的贪婪运算符在Tcl 8.5中不起作用

时间:2015-03-24 08:56:38

标签: regex perl tcl regex-greedy

请参阅此简单的正则表达式代码:

puts [ regexp -inline {^\-\-\S+?=\S+} "--tox=9.0" ]

输出结果为:

 >--tox=9

似乎第二个\ S +非贪婪!只匹配1个字符
在PERL中,人们可以看到结果如我所料,见1行输出:

perl -e '"--tox=9.0" =~/(^\-\-\S+?=\S+)/ ; print "${1}\n"'
--tox=9.0

如何在Tcl中获取Perl行为?

3 个答案:

答案 0 :(得分:5)

这是一项固有的功能' Tcl的正则表达式实现。例如,below来自Henry Spencer(即使不是全部Tcl&#39的正则表达式工作,我也相信)

  

很难想出一个完全令人满意的   混合贪婪正则表达式行为的定义。   Perl并没有尝试:Perl"规范"是一个描述   实施,一种涉及的固有的低性能方法   一次尝试一场比赛。对于许多人来说这是不能令人满意的   原因,尤其是它只需要几页文本   形容它。 (该实现及其描述很遥远,   我之前的一个正则表达式包的后代变异,所以我分享   一些责任归咎于此。)

     

当所有量词都贪婪时,Tcl 8.2正则表达式匹配   最长的匹配(如POSIX标准中所规定的那样)   正则表达式定义)。当所有人都不贪婪时,它就会匹配   最短的比赛。这些令人满意的陈述都不是   Perl的确如此。

     

麻烦的是,编写泛化是非常非常困难的   那些涵盖混合贪婪正则表达式的陈述 -   什么是适当的,与实现无关的定义   混合贪婪正则表达式匹配 - 并使它们成为现实   做"人们的期望"。我试过了。我还在努力。没有运气   远。

     

Tcl 8.2 regexp中的规则,基本上给出了整个正则表达式   基于其子表达式的长/短偏好是我最好的   到目前为止提出来了。代码准确地实现了它们。我同意   他们没有达到真正想要的水平。它比它更棘手   外观。

基本上,混合贪婪和非贪婪量词的表达式会影响实现的简单性和性能。因此,实现使得第一个类型'量词的传递给所有其他量词。

换句话说,如果第一个量词是贪婪的,那么所有其他量词都会贪婪。如果第一个是非贪婪的,那么所有其他人都不会贪婪。因此,您不能强制Tcl正则表达式像Perl正则表达式那样工作(或者您可以通过exec并使用perl的bash命令版本,但我对此并不熟悉。)

我建议使用否定的类和/或锚点而不是非贪婪的。

由于我不知道你问题的确切背景,我不会提供另一种正则表达式,因为这取决于这是否真的是你想要匹配的整个字符串。

答案 1 :(得分:3)

Tcl正则表达式引擎是一个自动机理论引擎而不是基于堆栈的引擎,所以它有一个非常不同的方法来匹配混合贪婪RE。特别是,对于你所谈论的那种RE,这将被解释为完全不贪婪。

解决此问题的最简单方法是使用不同的RE。请注意\S只是[^\s]的简写,我们可以执行此操作(从第一部分中排除=):

puts [ regexp -inline {^--[^\s=]+=\S+} "--tox=9.0" ]

(我还将\-更改为-,因为它不是Tcl RE中的特殊字符。)

答案 2 :(得分:2)

答案可以找到here

  

不幸的是,答案是得到Perl给出的相同答案,   你必须使用Perl的精确正则表达式实现。

在您的情况下,我会使用两个锚^$

  puts [ regexp -inline {^\-\-\S+?=\S+$} "--tox=9.0" ]

结果是:--tox=9.0