如何在Perl中的数组中存储正则表达式捕获?

csk*_*wrd 64 regex arrays perl

我正在尝试在Perl中使用正则表达式.我想知道是否可以将表达式的所有匹配存储到数组中?我知道我可以使用以下内容:($1,...,$n) = m/expr/g;但似乎只有在您知道要查找的匹配项数时才能使用.我尝试过,my @array = m/expr/g;但似乎没有用.

谢谢你的帮助!

fri*_*edo 78

如果您正在进行全局匹配(/g),则列表上下文中的正则表达式将返回所有捕获的匹配项.简单地说:

my @matches = ( $str =~ /pa(tt)ern/g )
Run Code Online (Sandbox Code Playgroud)

这个命令例如:

perl -le '@m = ( "foo12gfd2bgbg654" =~ /(\d+)/g ); print for @m'
Run Code Online (Sandbox Code Playgroud)

给出输出:

12
2
654
Run Code Online (Sandbox Code Playgroud)

  • @ysth.没有括号,它的可读性要差得多. (11认同)
  • 不需要(),=〜是一个高优先级运算符 (10认同)
  • 一定要使用"如果你在windows'shell中试试这个,就像这样,perl -le"@m =('foo12gfd2bgbg654'=〜/(\ d +)/ g); 打印@m"否则会出错,因为shell使用"作为字符串分隔符 (3认同)

Eth*_*her 17

请参阅"在列表上下文中匹配"下perldoc perlop的手册条目:

如果未使用/ g选项,则m //在列表上下文中返回一个列表,该列表由模式中括号匹配的子表达式组成,即($ 1,$ 2,$ 3 ......)

/ g修饰符指定全局模式匹配 - 即在字符串中尽可能多地匹配.它的行为取决于上下文.在列表上下文中,它返回正则表达式中任何捕获括号匹配的子字符串列表.如果没有括号,则返回所有匹配字符串的列表,就好像整个模式周围有圆括号一样.

您可以通过分配数组或以其他方式在列表上下文中执行评估来获取所有匹配项:

my @matches = ($string =~ m/word/g);
Run Code Online (Sandbox Code Playgroud)


cod*_*lic 17

有时你需要全局获得所有匹配,就像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);
Run Code Online (Sandbox Code Playgroud)

它打印

$VAR1 = [
          [
            'Philip',
            'Fry'
          ],
          [
            'Bender',
            'Rodriguez'
          ],
          [
            'Turanga',
            'Leela'
          ]
        ];
Run Code Online (Sandbox Code Playgroud)

  • 非常方便的技术; 如果不知道捕获组的数量,有没有办法概括这个?看起来你可能需要一个包含`($ 1,$ 2,...)`的特殊数组变量,但我找不到这样的东西. (3认同)
  • @mklement0 是的,在 Perl 5.25.7 中,添加了变量 `@{^CAPTURE}`。它包含上次成功匹配的“($1, $2, ...)”。为了概括上面的答案,请执行 `push @matches, [@{^CAPTURE}] while $subject =~ /(\w+) (\w+)/g;` (2认同)

Fli*_*imm 8

我认为这是一个不言自明的例子.注意/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")
Run Code Online (Sandbox Code Playgroud)

请记住,您需要确保左值位于列表上下文中,这意味着您必须用括号括起标量值:

($one, $two) = $string =~ m/(\w+) (\w+)/;
Run Code Online (Sandbox Code Playgroud)