0

我有一个以 hh:mm:ss 格式包含一次或多次的字符串。我创建了这个正则表达式来尝试通过分组来节省时间,这样我就可以做一些工作:

if ( $s =~ /(.*)(\d{2}:\d{2}:\d{2})(.*)(\d{2}:\d{2}:\d{2})(.*)(\d{2}:\d{2}:\d{2})(.*)/ )
{
  my @t = ( $2, $5, $8 );
  # loop through times and do stuff
}
else
{
  # no match found
}

问题是字符串可能有一个、两个或三个嵌入时间——而且这个正则表达式似乎只在三个都存在时才有效(不是一两个)。有没有更好的方法来做到这一点(并避免任何“使用未初始化的值”警告!)?

我试过这个,但它只抓住了最后一次:

/(.*)(\d{2}:\d{2}:\d{2})(.*)(\d{2}:\d{2}:\d{2})?(.*)(\d{2}:\d{2}:\d{2})?(.*)/ 
4

1 回答 1

8

g局部匹配以重复模式。如果您要做的只是将它们立即分配给一些更好命名的变量,请避免使用 backref 变量;匹配运算符已返回捕获缓冲区结果。

use Data::Dumper qw(Dumper);
my $timestamp = qr'
    (?<!\d)            # avoid digits before
    \d{2}:\d{2}:\d{2}  # hh:mm:ss
    (?!\d)             # avoid digits after
'x;

for my $s (qw(
    foo18:00:00bar18:00:00baz18:00:00quux
    foo18:00:00bar18:00:00baz
    foo18:00:00bar
)) {
    if (my @t = $s =~ /($timestamp)/g) {
        print Dumper \@t;
    }
}
于 2012-04-22T16:03:30.360 回答