我遇到了perl正则表达式匹配的问题。我把它降级到命令行上的一个小例子。为什么在这里尝试匹配的顺序很重要?
1
$ echo "XYG" | perl -ne 'if ($_ =~ m/X/gi) { print "Matches X\n"; } ; if ($_ =~ m/Y/gi) { print "Matches Y\n"; } ; if ($_ =~ m/G/gi) { print "Matches G\n"; } '
Matches X
Matches Y
Matches G
2
$ echo "GXY" | perl -ne 'if ($_ =~ m/X/gi) { print "Matches X\n"; } ; if ($_ =~ m/Y/gi) { print "Matches Y\n"; } ; if ($_ =~ m/G/gi) { print "Matches G\n"; } else { print "No match on G\n"; } '
Matches X
Matches Y
No match on G
1.示例按预期匹配所有三个字母,但第二个示例与字母G不匹配,为什么?
但是如果我创建一个中间变量,这里命名为$ aa:
$ echo "GXY" | perl -ne 'if ($_ =~ m/X/gi) { print "Matches X\n"; } ; if ($_ =~ m/Y/gi) { print "Matches Y\n"; } ; $aa = $_; if ($aa =~ m/G/gi) { print "Matches G\n"; } '
Matches X
Matches Y
Matches G
然后比赛再次起作用?
我的perl版本是:
$ perl -e 'print "$]\n";'
5.022001
在LM 18.2机器上
$ lsb_release -d
Description: Linux Mint 18.2 Sonya
泰+ BR 最大
答案 0 :(得分:5)
因为如果你在这样的标量上下文中匹配正则表达式,并设置g
标志(用于全局匹配)它是迭代的 - 那就是允许你做while ( m/somepattern/g ) {
这样的事情并拥有它触发多次。
那是因为g
表示:
g - 在字符串
中重复全局匹配模式
如果每次尝试重置它都不是特别有用。但是你也可以在数组上下文中略微使用它:
my @matches = $str =~ m/(some_capture)/g;
然后将它们全部选入列表中。
但是你的代码和正则表达式调试:
#!/usr/bin/env perl
use strict;
use warnings;
use re 'debug';
$_ = 'GXY';
if ( $_ =~ m/X/gi ) { print "Matches X\n"; }
if ( $_ =~ m/Y/gi ) { print "Matches Y\n"; }
if ( $_ =~ m/G/gi ) { print "Matches G\n"; }
else { print "No match on G\n"; }
你会得到(为了简洁起见):
Matching REx "X" against "GXY"
Matching REx "Y" against "Y"
Matching REx "G" against ""
第一场比赛'吃''GX'找到“X”,留下“Y”表示下一场比赛,但没有任何比赛用于“G”比赛。
简单的解决方法是省略g
标记,因为那时你明确地说'匹配一次',你会得到:
Matches X
Matches Y
Matches G
或者,您可以将全局匹配与字符类一起使用:
$_ = 'GXY';
my @matches = m/([GYX])/g; #implicitly operates on $_
print "Match on $_\n" for @matches;