perl:多个正则表达式中的匹配组

时间:2017-02-20 22:50:55

标签: regex perl

我想知道perl中是否有一些聪明的技巧我不知道要做以下事情:

my $re1 = qr/^(keyword\s+)(.*)$/;    
my $re2 = qr/^(otherkeyword\s+)(.*)$/;
my $re3 = qr/^(keyword_re3\s+)(.*)$/;

# there's around 20 expressions in reality, but I'll stick with 3 for the
# question...

my $testString = "otherkeyword xxxxx";

my ($keyword,$param) = $testString =~ /(?:$re1)|(?:$re2)|(?:$re3)/;

问题当然是$keyword$param都是空白的,因为$1$2是指$re1中的捕获组。

我可以遍历正则表达式,并在匹配时停止,但编译和运行单个正则表达式似乎更有效。当然,如果我这样做,我需要一种方法来确定它匹配的特定正则表达式$1$2是什么。我可以尝试命名捕获组,但这些正则表达式用于生成其他正则表达式,它会使程序复杂化很多。我希望有一种更清洁的方法来做到这一点。

3 个答案:

答案 0 :(得分:3)

到目前为止最干净的方法是使用分支重置模式 (?| ... | ... | ... ),它会重置每个交替分支中捕获变量的编号

看起来像这样

use strict;
use warnings 'all';

use Data::Dumper;
$Data::Dumper::Terse = 1;

my $re1 = qr/^(keyword\s+)(.*)$/;
my $re2 = qr/^(otherkeyword\s+)(.*)$/;
my $re3 = qr/^(keyword_re3\s+)(.*)$/;

my $testString = "otherkeyword xxxxx";
my ($keyword, $param) = $testString =~ /(?|(?:$re1)|(?:$re2)|(?:$re3))/;

print Dumper [ $keyword, $param ];

输出

[
  'otherkeyword ',
  'xxxxx'
]

答案 1 :(得分:2)

如果模式之间存在显着差异(即捕获不同数量的事物),您可以通过以下方式解决不同的捕获组:

my ($keyword,@param) = grep defined, $testString =~ /(?:$re1)|(?:$re2)|(?:$re3)/;

否则,只需制作一个正则表达式:

my @keyword = qw/keyword otherkeyword keyword_re3/;
my $keywords = join '|', map quotemeta, @keyword;
my $keyword_re = qr/^($keywords\s+)(.*)$/;

(你真的想拍摄空格吗?)

答案 2 :(得分:1)

此处的另一种选择是使用命名组,例如:

#!/usr/bin/perl

use strict;
use warnings;

my $re1 = qr/^(?:keyword\s+)(?<keyword>.*)/;
my $re2 = qr/^(?:otherkeyword\s+)(?<otherkeyword>.*)/;
my $re3 = qr/^(?:keyword_re3\s+)(?<keyword_re3>.*)/;

my $testString = "otherkeyword xxxxx";
if ($testString =~ /^(?:$re1|$re2|$re3)$/)
{
    for my $keyword (keys %+)
    {
        print "$keyword = $+{$keyword}\n";
    }
}

打印出&#34; otherkeyword = xxxxx&#34;你似乎想要。