是否可能将正则表达式的所有匹配项存储到数组中?
我知道可以使用($1,...,$n) = m/expr/g;
,但似乎只有在您知道要查找的匹配项数量时才能使用。我尝试过my @array = m/expr/g;
,但似乎不起作用。
如果您正在进行全局匹配(/g
),则在列表上下文中使用的正则表达式将返回所有捕获的匹配项。只需执行以下操作:
my @matches = ( $str =~ /pa(tt)ern/g )
比如这个命令:
perl -le '@m = ( "foo12gfd2bgbg654" =~ /(\d+)/g ); print for @m'
给出输出:
12
2
654
perl -le '@m = ( (my $s = "foo12gfd2bgbg654") =~ s/(\d+)//g ); print for @m'
只会打印出 3
。 - U. Windls/.../.../g
的返回值,它返回所做的替换次数。唯一可以在替换中使用捕获值的地方是替换值。例如:s/(\d+)/找到数字 $1/g
。 - Francisco Zarabozo有时候需要全局匹配所有符合条件的结果,类似于 PHP 中的 preg_match_all
函数。如果你需要这样做,可以写出如下代码:
# a dummy example
my $subject = 'Philip Fry Bender Rodriguez Turanga Leela';
my @matches;
push @matches, [$1, $2] while $subject =~ /(\w+) (\w+)/g;
use Data::Dumper;
print Dumper(\@matches);
它打印出来
$VAR1 = [
[
'Philip',
'Fry'
],
[
'Bender',
'Rodriguez'
],
[
'Turanga',
'Leela'
]
];
($1, $2, ...)
,但我找不到这样的东西。 请问是否可以让这个技巧更加通用化,以应对捕获组数量未知的情况?似乎需要使用一个特殊的数组变量,将所有捕获组都包含进去(如 $1
, $2
等),但我找不到这样的变量。 - mklement0@{^CAPTURE}
,它包含最后一个成功匹配的($1, $2, ...)
。为了概括上面的答案,请执行 push @matches, [@{^CAPTURE}] while $subject =~ /(\w+) (\w+)/g;
。 - Viktor Söderqvist请参阅perldoc perlop中“匹配列表上下文”部分的手册:
如果没有使用/g选项,m//在列表上下文中返回一个列表,其中包含模式中括号匹配到的子表达式,即($1, $2, $3 ...)。
/g修饰符指定了全局模式匹配--也就是在字符串中尽可能多地匹配。它的行为取决于上下文。在列表上下文中,它返回与正则表达式中所有捕获括号匹配的子字符串的列表。如果没有括号,则返回匹配的所有字符串的列表,好像整个模式都有括号。
您可以通过分配到数组或以列表上下文执行评估来简单地获取所有匹配项:
my @matches = ($string =~ m/word/g);
我认为这是一个不需要解释的例子。请注意第一个正则表达式中的 /g
修饰符:
$string = "one two three four";
@res = $string =~ m/(\w+)/g;
print Dumper(@res); # @res = ("one", "two", "three", "four")
@res = $string =~ m/(\w+) (\w+)/;
print Dumper(@res); # @res = ("one", "two")
($one, $two) = $string =~ m/(\w+) (\w+)/;
@{^CAPTURE}
被添加了进来,它保存着“上一次成功匹配的模式的捕获缓冲区内容(如果有的话)”即展示了($1, $2, ...)
的内容即使不确定捕获组数。 在Perl 5.25.7之前(自5.6.0版本以来),您可以使用@-
和@+
构建相同的数组,如@Jaques在他的答案中所建议的那样。 这需要做以下操作: my @capture = ();
for (my $i = 1; $i < @+; $i++) {
push @capture, substr $subject, $-[$i], $+[$i] - $-[$i];
}
我很惊讶这里还没有提到,但是Perl文档提供了标准变量@+
。引用文档内容:
此数组保存当前活动动态范围内最后一个成功的子匹配的起始偏移量。
因此,要获取第一个捕获到的值,可以编写以下代码:
print substr( $str, $-[1], $+[1] - $-[1] ), "\n"; # equivalent to $1
%-
,它不仅包含命名捕获,而且允许重复名称存储在数组中。/(?<A>1)(?<B>2)(?<A>3)(?<B>4)/
$-{A}[0] : '1'
$-{A}[1] : '3'
$-{B}[0] : '2'
$-{B}[1] : '4'
my $mess = <<'IS_YOURS';
Richard Rich
April May
Harmony Ha\rm
Winter Win
Faith Hope
William Will
Aurora Dawn
Joy
IS_YOURS
使用以下正则表达式
my $oven = qr'^(\w+)\h+(\w+)$'ma; # skip the /a modifier if using perl < 5.14
我可以在下面的@box
中捕获所有12个(6对,不是8个...Harmony逃脱了,Joy失踪了)。
my @box = $mess =~ m[$oven]g;
my %hash = @box;
或者我本来就可以完全跳过这个框。
my %hash = $mess =~ m[$oven]g;
%hash
包含以下内容。顺序丢失并且重复的键(如果存在)被压缩:(
'April' => 'May',
'Richard' => 'Rich',
'Winter' => 'Win',
'William' => 'Will',
'Faith' => 'Hope',
'Aurora' => 'Dawn'
);
($1, $2)
来获取所有匹配项。 - U. Windl
($1, ...) = ...
是一个非常糟糕的例子,应该进行编辑。这会让人感到困惑,因为捕获组已经设置了$1
。那么你为什么要重新赋值呢(如果允许的话)? - U. Windl