perl解释中的正则表达式

时间:2014-07-31 21:34:21

标签: regex perl

我需要帮助理解下面的正则表达式。

有人可以告诉我这意味着什么m/^(\d+\/\d+\/\d+\s\d+\:\d+\:\d+\.\d+)/msx

foreach my $line ( @{ $self->{'stdout'} } ) {
        if ( $line =~ m/^(\d+\/\d+\/\d+\s\d+\:\d+\:\d+\.\d+)/msx ) {
            $timestamp = $1;
        }

2 个答案:

答案 0 :(得分:1)

这个原始正则表达式

m/^(\d+\/\d+\/\d+\s\d+\:\d+\:\d+\.\d+)/msx

是一个编写得非常糟糕的模式,与日期/时间字符串相匹配,看起来像2014/07/31 22:53:42.123

由于它不包含任何点.,因此/s修饰符是多余的。

/x修饰符允许添加空格布局,所以我们也可以使用不同的分隔符,以便斜线不需要转义

m{ ^ ( \d+ / \d+ / \d+ \s \d+ : \d+ : \d+ \. \d+ ) }mx

这样匹配

  • 从任何行的开头(即在字符串的开头或在换行符之后,因为/m修饰符生效)
  • 捕获以下内容
  • 一些数字,一个斜线,一些更多的数字,另一个斜线,一些更多的数字
  • 一个空格字符(这里我认为是一个空格)
  • 一些数字,一个冒号,一些更多的数字,另一个冒号,一些更多的数字,一个点,一些更多的数字
  • 停止捕获

所以,正如我所说,它会匹配(和捕获)

2014/07/31 22:53:42.123

它也匹配

0/1/2 3:4:5.6

我希望有帮助

答案 1 :(得分:1)

if ( $line =~ m/^(\d+\/\d+\/\d+\s\d+\:\d+\:\d+\.\d+)/msx ) {

是非常难以理解的,尽管作者开始让它可读,因为它有/x标志(允许空格,但没有使用),但它仍然受到反斜视的影响并且不限制与真正的意义相匹配。

使用不同的分隔符重写它可以去掉一些反斜杠:

if ( $line =~ m{^(\d+/\d+/\d+\s\d+:\d+:\d+\.\d+)}msx ) {

添加空格并使用[.]来匹配单个点并添加注释可以更好地了解匹配的内容:

if ( $line =~ m{^       # (start of line)
    (                   # (capture group $1)
        \d+ / \d+ / \d+ # digit(s) slash digit(s) slash digit(s)
        \s              # ANY whitespace character (space, tab, etc)
        \d+ : \d+ : \d+ # digit(s) colon digit(s) colon digit(s)
        [.] \d+         # dot digit(s)
    )                   # (end capture group $1)
}msx ) {

其中digit(s)表示一个或多个数字0-9(或任何utf8数字)。因此,这将很乐意匹配类似“00000/0000/0000000000 0000:0000000000000000000000:000000.0000”的内容,但似乎它们意味着匹配,例如“0000/00/00 00:00:00.000”(时间戳包括毫秒)。

一个更好的正则表达式(匹配它不应该匹配的东西的可能性更低,虽然它固定在线的开头,所以这里没有真正的实际区别,但作为一般规则,最好尽可能具体到你可以)会是这样的:

if ( $line =~ m{^
    (
        [0-9]{4} / [0-9]{2} / [0-9]{2}
        [ ]                   # space character
        [0-9]{2} : [0-9]{2} : [0-9]{2}
        [.] [0-9]{3}
    )
}msx ) {

有了这方面的话,其他链接的正则表格联机手册应该更有意义。