我使用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
实际上做的。
是否有任何简单的方法可以返回成功的交替,或者我是否需要尝试其他方法。
答案 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的错误。