【问题标题】:Perl successful alternation matchPerl 成功的交替匹配
【发布时间】:2016-07-20 18:39:36
【问题描述】:

我使用 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 实际所做的。

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

【问题讨论】:

  • 您指的是文档的哪一部分?

标签: regex perl


【解决方案1】:

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

捕获组具有跨越交替的连续编号,并且引入了(?|...) 构造来解决这个问题。详情请见http://perldoc.perl.org/perlretut.html#Alternative-capture-group-numbering

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

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

【讨论】:

    【解决方案2】:

    你的最终模式

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

    有九个捕获:三个在$regexdate,三个在$regextime,另外三个在$regexdate的第二个副本中

    虽然您可以像这样使用“分支重置”构造

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

    将时间字段设为可选会更有意义,就像这样

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

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

    【讨论】:

    • 这有助于我理解 Perl 正则表达式,目前我使用的是可选时间,但会进一步探索。每个人都想改变我的ISO 8601[-][:] 在基本格式中是可选的(我退休后没有ISO 8601 的副本)。我从来没有打算严格遵循 ISO 8601 而是“风格”并使用常见的变体,包括 [_][.] 以及缺少时间分隔符。
    • @Milliways: ISO 8601
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2020-06-05
    • 2013-11-03
    • 1970-01-01
    • 2012-12-06
    相关资源
    最近更新 更多