Perl成功交替比赛

时间:2016-07-20 05:49:53

标签: regex perl

我使用Regex来匹配ISO8601样式的日期/时间或日期,使用以下内容: -

my $regexdate = qr/((?:19|20)[[:digit:]]{2})[-]?([[:digit:]]{2})[-]?([[:digit:]]{2})/;
my $regextime = qr/([[:digit:]]{2})[:]?([[:digit:]]{2})[:]?([[:digit:]]{2})/;
my $datime = qr/(?:$regexdate[ T]?$regextime)|$regexdate/;

我虽然在列表上下文中使用匹配结果会更容易,但是尝试了: -

my @result =  ($file =~ m/$datime/p);

当我尝试打印时,我收到了一些uninitialized value警告,表明该列表包含9个元素,而不是我期待的6或3个元素。

print "$file\t=> ${^MATCH}\t@result\n";

我只希望成功的替换匹配返回值,我阅读文档显然不是Perl实际上做的。

是否有任何简单的方法可以返回成功的交替,或者我是否需要尝试其他方法。

2 个答案:

答案 0 :(得分:1)

使用(?|...)构造。

捕获组在交替期间具有连续编号,并且已引入(?|...)构造来解决此问题。有关详细信息,请参阅http://perldoc.perl.org/perlretut.html#Alternative-capture-group-numbering

因此,通过这个次要但重要的更改,您的代码可能如下所示:https://ideone.com/ux3Ndz

在您的特定情况下,还有另一种解决此问题的方法。您可以将日期部分设为可选($date[ T]$time|$date),而不是使用替换(即$date(?:[ T]$time)?),从而消除了交替组编号问题。 Here就是一个例子。我还将Posix类更改为Perl类,并删除了不必要的char类括号([...])以使代码更简洁。

答案 1 :(得分:0)

你的最终模式

qr/(?:$regexdate[ T]?$regextime)|$regexdate/

有9个捕获:$regexdate中有3个,$regextime中有3个,$regexdate的第二个副本中有3个

虽然可以使用“分支重置”结构,但是这样

qr/(?|$regexdate[ T]$regextime|$regexdate)/

简单地将时间字段设为可选,就像这样

qr/$regexdate(?:[ T]$regextime)?/

注意 我已从空格/ T中删除了将日期与时间分开的量词,因为它在ISO8601中是非可选的。我也不明白为什么你在成分正则表达式中使日期和时间字段分隔符[-][:]可选。这也是ISO8601的错误。