3

所以我试图从日志行中删除嵌入的 \n 而不从命令行中删除每个日志行的 \n 。我已经尝试过这些,它们都将 \n 全部更改为 ~。

    cat test1.txt | perl -n -e 's{\n(?!2013)}{~}mg;print' > test1a.fix
    perl -n -e 's{\n(?!2013)}{~}mg;print' test1.txt > test1b.fix

都忽略了背后的负面目光。

test1.txt 包含

    2013-03-01 12:23:59,1
    line2
        line3
    2013-03-01 12:23:59,4

包含 test1a.fix 和 test1b.fix

    2013-03-01 12:23:59,1~line2~    line3~2013-03-01 12:23:59,4

但我想出了使用这个脚本的正则表达式。

    #!/usr/bin/perl
    use warnings;
    use strict;

    sub test {
        my ($str, $expect) = @_;
        my $mod = $str;
        $mod =~ s{\n(?!2013)}{~}mg;
        print "Expecting '$expect' got '$mod' - ";
        print $mod eq $expect ? "passed\n" : "failed\n";
    }

    test("2013-03-01 12:23:59,line1
    line2
        line3
    2013-03-01 12:23:59,line4", "2013-03-01 12:23:59,line1~line2~    line3
    2013-03-01 12:23:59,line4");

它会产生与我想要的匹配的以下输出。

    sfager@linux-sz05:~/logs> ./regex_test.pl 
    Expecting '2013-03-01 12:23:59,line1~line2~    line3
    2013-03-01 12:23:59,line4' got '2013-03-01 12:23:59,line1~line2~    line3
    2013-03-01 12:23:59,line4' - passed
    sfager001@linux-sz05:~/logs> 

谁能解释为什么这些工作方式不同以及如何在命令行上完成?

4

2 回答 2

4

perl -n一次处理一行文件。当它读取一行时,换行符位于字符串的末尾,而不是您的正则表达式所期望的开头。您应该使用^来匹配行的开头而不是\n.

在函数版本中,您一次处理整个多行字符串。在这种情况下,换行符位于字符串的中间,它们与正则表达式匹配。

于 2013-03-31T20:59:28.333 回答
2

您的命令行程序一次只能看到一个“输入记录”(又名行)。通过踩下输入记录分隔符变量 $/,我能够让您的示例正常工作。

perl -n -e '$/=undef; s{\n(?!2013)}{~}mg;print' test1.txt > test1c.fix

这将每个“行”重新定义为整个输入,并且实际上让它更像您的脚本一样工作。

cat test1c.fix
2013-03-01 12:23:59,1~line2~    line3
2013-03-01 12:23:59,4~
于 2013-03-31T21:13:24.293 回答