我想知道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
是什么。我可以尝试命名捕获组,但这些正则表达式用于生成其他正则表达式,它会使程序复杂化很多。我希望有一种更清洁的方法来做到这一点。
答案 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;你似乎想要。