我已经使用perl十年了。但最近我对使用它感到困惑。*?正则表达式。
它似乎与最小字符数不匹配。有时会产生不同的结果。
例如,对于这个字符串:aaaaaaaaaaaaaaaaaaaaaaammmmmmmmmmbaaaaaaaaaaaaaaaaaaaaaa和pattern:a。*?b它匹配两组中的完整输入字符串。根据定义,它应该与最后的“ab”相匹配。
答案 0 :(得分:8)
示例缩写为:
'aaab' =~ /a.*?b/
会发生什么:
a
匹配a
。.*?
匹配尽可能少的字符数(0),匹配空字符串。b
无法匹配。 ⇒回溯.*?
匹配尽可能少的字符数(1),匹配a
b
无法匹配。 ⇒回溯.*?
匹配尽可能少的字符数(2),匹配aa
b
匹配b
。我尽量避免使用非贪婪的修饰符。
'aaab' =~ /a[^a]*b/
如果a
确实更复杂,那么就可以使用否定前瞻。
'aaab' =~ /a(?:(?!a).)*b/
答案 1 :(得分:6)
这意味着
. # match any character except newlines
* # zero or more times
? # matching as few characters as possible
所以在
<tag> text </tag> more text <tag> even more text </tag>
正则表达式<tag>(.*)</tag>
将立即匹配整个字符串,捕获
text </tag> more text <tag> even more text
在后向引用号1中。
如果您将其与<tag>(.*?)</tag>
相匹配,则会获得两场比赛:
<tag> text </tag>
<tag> even more text </tag>
仅分别在反向引用号1中捕获text
和even more text
。
如果(感谢Kobi!)你的源文本是
<tag> text <tag> nested text </tag> back to first level </tag>
然后您会发现<tag>(.*)</tag>
再次与整个字符串匹配,但<tag>(.*?)</tag>
将匹配
<tag> text <tag> nested text </tag>
因为正则表达式引擎从左到右工作。这是正则表达式“不是匹配无上下文语法的最佳工具”的原因之一。
答案 2 :(得分:4)
它匹配最小数量的字符,从可匹配的第一个位置开始,这允许正则表达式的其余部分匹配。中间部分(从...开始)是正则表达式状态机运行方式所固有的。 (编辑进一步澄清)
答案 3 :(得分:1)
它应该匹配整个模式成功匹配所需的最小字符数(如果匹配则完全匹配)。你能提供一个不这样做的具体例子吗?
答案 4 :(得分:1)
我不认为你可以在你的情况下直接匹配ab。通常当.*?
不起作用时,它会调用[^c]*
模式,其中c是字符或字符类。这可以防止误报匹配
但在这种情况下,它不起作用:a[^a]*b
首先匹配ammmmmmmmmmmb
。因此,找到最短匹配的唯一方法是找到所有匹配,然后选择最短的匹配。
下面是一个详细的(你说你有一段时间没有使用过Perl; - )获得你想要的结果的方法:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(reduce); # see List::Util docs for what reduce does
my $s= "aaaaaaaaaaaaaaaaaaaaaaammmmmmmmmmmbaaaaaaaaaaaaaaaaaaaaaab";
my $RE= qr/a[^a]*b/;
print "regexp: $RE\n"; # ammmmmmmmmmmb
print "single match:\n";
if( $s=~ m{($RE)}) { print " $1\n"; }
print "all matches (loop):\n"; # ammmmmmmmmmmb \n ab
while( $s=~ m{($RE)}g)
{ print " - $1\n"; }
print "all matches (in an array):\n"; # ammmmmmmmmmmb - ab
my @matches= $s=~ m{(a[^a]*b)}g;
if( @matches) { print " ", join( " - ", @matches), "\n"; }
print "\nshortest match: "; # ab
print reduce { length $a < length $b ? $a : $b } @matches;
print "\n";
简而言之,延迟匹配与获取字符串中的最短匹配不同。对于rexegp引擎Perl(我相信大多数其他语言)使用这种最短匹配并不是一个简单的问题。
答案 5 :(得分:0)
请举一个具体的例子,我们可以用它来重现您遇到的有问题的行为。
您正在使用正确的构造,因此可能在您的查询的其余部分中存在问题。我也遇到过问题,但总是想到这是由于我的如意解析 - 即我希望正则表达式解析我的意思,而不是我输入的方式:)