1美元和多个分组

时间:2014-04-15 01:44:52

标签: regex perl

如果我有一个正则表达式,并且我希望其中一个或哪个术语匹配,请说

ab*cc or ab*dd

我有像RegEx一样的

while($line =~ /(ab*cc)|(ab*dd)/g)
{
    # print match whether its abcc or abdd
    # print $1?
}

但我不确定$1将如何运作。 是否存在$2这样的事情,如果它与abcc匹配则为$1,如果匹配abdd则为$2?如果我说3组左右,这意味着它可以是X,Y还是Z,我该如何扩展呢?

2 个答案:

答案 0 :(得分:3)

您可以使用:

while ($line =~ m/((ab*cc)|(ab*dd))/g)

现在$1将是两个术语匹配中的任何一个,$2如果第一个术语匹配则相同但是未定义,而$3如果第二个匹配则相同术语匹配但未定义。三个或更多术语的扩展应该是显而易见的。


m//符号是一种略微更明确的符号,等同于//。否则,它不会改变事物。 $1等值由开括号(的顺序决定。外部对包裹了所有匹配的东西;两个内部对捕获术语。请注意,如果您有m/((ab*cc)+|(ab*dd)+))/g,则$2$3的内容将是重复术语的最后一项,而不是重复术语的完整集合。

示例1

$ cat example2.pl
#!/usr/bin/env perl
use strict;
use warnings;

while (my $line = <>)
{
    chomp $line;
    print "Line: <<$line>>\n";
    while ($line =~ m/((ab*cc)|(ab*dd))/g)
    {
        printf "\$1 = <<%s>>; \$2 = <<%s>>; \$3 = <<%s>>\n",
               $1 // "undef", $2 // "undef", $3 // "undef";
    }
}
$ perl example1.pl
abbccabccaccaddabddabbdddabbbdddd
Line: <<abbccabccaccaddabddabbdddabbbdddd>>
$1 = <<abbcc>>; $2 = <<abbcc>>; $3 = <<undef>>
$1 = <<abcc>>; $2 = <<abcc>>; $3 = <<undef>>
$1 = <<acc>>; $2 = <<acc>>; $3 = <<undef>>
$1 = <<add>>; $2 = <<undef>>; $3 = <<add>>
$1 = <<abdd>>; $2 = <<undef>>; $3 = <<abdd>>
$1 = <<abbdd>>; $2 = <<undef>>; $3 = <<abbdd>>
$1 = <<abbbdd>>; $2 = <<undef>>; $3 = <<abbbdd>>
$

示例2

$ cat example2.pl
#!/usr/bin/env perl
use strict;
use warnings;

while (my $line = <>)
{
    chomp $line;
    print "Line: <<$line>>\n";
    while ($line =~ m/((ab*cc)+|(ab*dd)+)/g)
    {
        printf "\$1 = <<%s>>; \$2 = <<%s>>; \$3 = <<%s>>\n",
               $1 // "undef", $2 // "undef", $3 // "undef";
    }
}
$ perl example2.pl
abbccabccacc
Line: <<abbccabccacc>>
$1 = <<abbccabccacc>>; $2 = <<acc>>; $3 = <<undef>>
$

答案 1 :(得分:2)

捕获的括号按其外观顺序标记。在这样的或那样的组中,其中一个或哪个匹配。要测试哪个匹配,只需使用defined

while($line =~ /(ab*cc)|(ab*dd)/g)
{
    if (defined $1) {
         print "first group matched: $1";
    } elsif (defined $2) {
         print "second group matched: $2";
    }
}

如果您不关心区分哪个组匹配,只需在整个表达式周围使用单个括号

while($line =~ /(ab*cc|ab*dd)/g)
{
    print "Will hold whichever matched: $1";
}