在 Perl 中匹配多行格式不正确的文本

Matching multiple lines of poorly formatted text in Perl

我有来自外部程序的数据格式,如下所示,需要获取每行的前 4 个字段(文本、用户名、数字和时间戳)。请注意 Hello line1 是一个字段,第二个是用户名。输出格式可以是单行,如下面的 line1 或三行,如 line2 或两行,如下面的 line4。而且格式也可以像下面这样混合(不是单行或双行等)

Hello Line1 FirstName.LastName 10 3/23/2011 2:46 PM

Hello Line2

                         Line2FirstName-LastName       8       7/17/2015 1:15 PM 

Line2Testing - 12323232323 Hello There

Hello Line3 Line3FirstName.LastName 8 3/21/2011 2:46 PM

Hello Line4

                         Line4FirstName-LastName       8       9/17/2015 1:20 PM

Screen shot of above in a editor

在这个问题的帮助下,我能够获得多行正则表达式:

感谢@GsusRecovery!

因为我是逐行阅读输出,所以我不认为我可以通过阅读单行来利用多行正则表达式。如果格式在一行中是否可以只读取一行或者如果它在 3 行中展开为 2 或 3 行是否可以读取 2 行?

还是根据双行或三行格式阅读每一行和回溯更好。

求推荐。

最好使用单一方法而不是在每行上切换,因为没有迹象表明 single/multi 行可以预先发生。因为您有 (int) 和 (date) 的固定格式,所以只需使用多行正则表达式模式,它会匹配如下内容:(伪正则表达式代码)

 \s+    (.*)   \s+  (.*)  (\d+) (\d+\/\d+\/\d+ \d+\:\d+ [AP]M)$
 space text  space  name  int   date

不要忘记使用 /m 进行多行匹配。因为 single/multi 行模式除了 \n 和额外的间距外几乎完全相同,所以在所有情况下都可以使用相同的模式。

更新:我已经更改脚本以接受标准输入并将其作为数组放入@output_lines(模拟@sureng 的输入情况)

我已将正则表达式包装在一个将小时识别为结束模式的行累加器中。通过这种方式,您可以逐行解析输出并应用正则表达式。

#!/usr/bin/perl

use strict;
use warnings;

my ($accumulator,$chat,$username,$chars,$timestamp);

my @output_lines = <STDIN>;

foreach (@output_lines)
{
    $accumulator .= $_;

   ($chat,$username,$chars,$timestamp) = $accumulator =~ m/(?im)^\s*(.+)\s+(\w+[-,\.]\w+)\s+(\d+)\s+([0-1]?\d\/[0-3]?\d\/[1-2]\d{3}\s+[0-2]?\d:[0-5]?\d\s?[ap]m)\s*$/;
    $chat =~ s/\s+$// if $chat;  #remove trailing spaces

    if ( $accumulator =~ /(?i)([0-2]?\d:[0-5]?\d\s?[ap]m)/ ) {
        print "SECTION matched\n";
        print "-"x80,"\n";
        print "$accumulator";
        print "-"x80,"\n";
        print "chat -> ${chat}\n";
        print "username -> ${username}\n";
        print "chars -> ${chars}\n";
        print "timestamp -> ${timestamp}\n\n";
        $accumulator = '';  # reset the line accumulator
    }
}

在线尝试解决方案(将您的示例作为标准输入提供)here

在你的 shell 中,给定上面的脚本和这个输入文件:

# MultiLineInput.txt
Hello Line1 FirstName.LastName 10 3/23/2011 2:46 PM

Hello Line2

                     Line2FirstName-LastName       8       7/17/2015 1:15 PM 
Line2Testing - 12323232323 Hello There

Hello Line3 Line3FirstName.LastName 8 3/21/2011 2:46 PM

Hello Line4

                     Line4FirstName-LastName       8       9/17/2015 1:20 PM

您只需拨打:

cat MultiLineInput.txt | StreamRegex.pl

如果它按预期工作,您可以用您的来源替换 cat 命令。

NB:如果你处理一个流或者如果你的文件大于系统的易失性内存(所以你想把它作为一个流来处理),就需要这种方法) 但是,也就是说,它在任何情况下都有效。