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一度に 1 行ずつファイルを処理します。行を読み取ると、正規表現が期待するように、改行は文字列の末尾にあり、先頭にはありません。^ではなく、行頭に一致させるために使用する必要があります\n

関数バージョンでは、複数行の文字列全体を一度に処理しています。この場合、改行は文字列の途中にあり、正規表現と一致します。

于 2013-03-31T20:59:28.333 に答える
2

コマンド ライン プログラムは、一度に 1 つの「入力レコード」(別名行) しか認識しません。入力レコード区切り変数 $/.

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 に答える