为什么此代码跳过其他所有输入行

时间:2019-10-08 21:02:34

标签: regex perl

我正在尝试通过正则表达式遍历数据并按日期解析每一行(即7/9/2019)。但是,结果将省略输入数据中的每隔一行。

在Windows和Mac(终端外壳)上始终尝试相同的行为。

my $file;

{
    local $/ = undef;
    $file = <DATA>;
}

while ($file =~ m/(\d\/\d\/\d{4}.*?)\d\/\d\/\d{4}/gs) {
    print "*$1*\n";
}

__DATA__
9/7/2019 20:35:17,dog
9/7/2019 21:06:16,cat
9/7/2019 22:32:15,parrot
9/7/2019 22:32:15,snail
9/7/2019

我希望以下几点:

*9/7/2019 20:35:17,dog*
*9/7/2019 21:06:16,cat*
*9/7/2019 22:32:15,parrot*
*9/7/2019 22:32:15,snail*

但是得到以下信息:

*9/7/2019 20:35:17,dog
*
*9/7/2019 22:32:15,parrot
*

2 个答案:

答案 0 :(得分:3)

您没有封装模式的结尾。将您的while循环更改为:

 while ($file =~ m/(\d\/\d\/\d{4}.*?)(?=\R\d\/\d\/\d{4})/gs) {
    print "*$1*\n";
}

那应该对您有用。在https://rextester.com/l/perl_online_compiler

进行测试

答案 1 :(得分:2)

您的模式匹配两个日期,因此下一个匹配将从那里开始,从而有效地跳过了这一行。

检查下一行是否以日期开头没有意义,因此您可以使用

while (<DATA>) {
   next if !m{^(\d+/\d+/\d+)};

   print "*$1*\n";
}

如果您不是从文件中读取:

while ($file =~ m{^(\d+/\d+/\d+)}mg) {
   print "*$1*\n";
}

如果每一行都以日期开头,您甚至可以使用

while (<DATA>) {
   my @fields = split;
   print "*$fields[0]*\n";
}

如果您不是从文件中读取:

while ($file =~ /^(.*)/mg) {
   my @fields = split;
   print "*$1*\n";
}

缺少/s意味着.与换行符不匹配,这意味着它将不与行尾匹配。