3

&&演算子が正規表現で機能するかどうかはわかりません。私がやろうとしているのは、数字で始まり文字「a」で次の行が数字で始まり文字「b」で次の行が文字「c」になるように行を一致させることです。このabcシーケンスは、ファイルの読み取りを開始するための一意の識別子として使用されます。

これが私がawkでやろうとしていることです。

/(^[0-9]+ .*a)&&\n(^[0-9]+ .*b)&&\n(^[0-9]+ .*c) {
print $0
}

これらの正規表現の1つだけが(^ [0-9]+。*a)のように機能しますが、それらをつなぎ合わせる方法がわかりません。次の行はこれです。

私のファイルは次のようになります:

JUNK UP HERE NOT STARTING WITH NUMBER
1     a           0.110     0.069          
2     a           0.062     0.088          
3     a           0.062     0.121          
4     b           0.062     0.121          
5     c           0.032     0.100         
6     d           0.032     0.100          
7     e           0.032     0.100   

そして私が欲しいのは:

3     a           0.062     0.121          
4     b           0.062     0.121          
5     c           0.032     0.100         
6     d           0.032     0.100          
7     e           0.032     0.100 
4

3 に答える 3

1

いいえ、うまくいきません。次のようなことを試すことができます:

/(^[0-9]+.*a[^\n]*)\n([0-9]+.*b[^\n]*)\n([0-9]+.*c[^\n]*)/

必要な文字数だけ繰り返します。

[^\n]*、行内の可能な限り多くの非改行文字に一致します (改行まで)。

于 2012-10-03T23:46:57.957 に答える
1

[明確化に基づいて更新。]

重要な点の 1 つは、Awk は行指向の言語であるため、通常のパターン マッチで行をまたぐことは実際にはできないということです。このようなことを行う通常の方法は、各行を個別に照合し、後の句/ステートメントで、すべての適切な部分が照合されたかどうかを判断することです。

ここで行っているのはa、ある行の 2 番目のフィールドで aを探しb、別の行の 2 番目のフィールドでa を探しc、3 行目の 2 番目のフィールドで a を探していることです。最初の 2 つのケースでは、行の内容と、それが発生した行番号を隠しておきます。3 行目が一致し、シーケンス全体がまだ見つかっていない場合は、戻って、他の 2 行が存在し、行番号が許容できるかどうかを確認します。すべて問題がなければ、バッファリングされた前の行を出力し、他のすべてを出力する必要があることを示すフラグを設定します。

スクリプトは次のとおりです。

$2 == "a" { a = $0; aLine = NR; }
$2 == "b" { b = $0; bLine = NR; }
$2 == "c" && !keepPrinting {
    if ((bLine == (NR - 1)) && (aLine == (NR - 2))) {
        print a;
        print b;
        keepPrinting = 1;
    }
}
keepPrinting { print; }

そして、これが私がテストしたファイルです:

JUNK UP HERE NOT STARTING WITH NUMBER
1     a           0.110     0.069
2     a           0.062     0.088
3     a           0.062     0.121
4     b           0.062     0.121
5     c           0.032     0.100
6     d           0.032     0.100
7     e           0.032     0.100
8     a           0.099     0.121
9     b           0.098     0.121
10    c           0.097     0.100
11    x           0.000     0.200

これを実行すると、次のようになります。

$ awk -f blort.awk blort.txt
3     a           0.062     0.121
4     b           0.062     0.121
5     c           0.032     0.100
6     d           0.032     0.100
7     e           0.032     0.100
8     a           0.099     0.121
9     b           0.098     0.121
10    c           0.097     0.100
11    x           0.000     0.200
于 2012-10-04T00:44:06.023 に答える
0

友人がこの awk プログラムを書いてくれました。ステートマシンです。そして、それは機能します。

#!/usr/bin/awk -f

BEGIN {
    # We start out in the "idle" state.
    state = "idle"
}

/^[0-9]+[[:space:]]+q/ {
    # Everytime we encounter a "# q" we either print it or go to the
    # "q_found" state.
    if (state != "printing") {
        state = "q_found"
        line_q = $0
    }
}

/^[0-9]+[[:space:]]+r/ {
    # If we are in the q_found state and "# r" immediate follows,
    # advance to the r_found state.  Else, return to "idle" and 
    # wait for the "# q" to start us off.
    if (state == "q_found") {
        state = "r_found"
        line_r = $0
    } else if (state != "printing") {
        state = "idle"
    }
}

/^[0-9]+[[:space:]]+l/ {
    # If we are in the r_found state and "# l" immediate follows,
    # advance to the l_found state.  Else, return to "idle" and 
    # wait for the "# q" to start us off.
    if (state == "r_found") {
        state = "l_found"
        line_l = $0
    } else if (state != "printing") {
        state = "idle"
    }
}

/^[0-9]+[[:space:]]+i/ {
    # If we are in the l_found state and "# i" immediate follows,
    # we're ready to start printing.  First, display the lines we
    # squirrelled away then move to the "printing" state.  Else,
    # go to "idle" and wait for the "# q" to start us off.
    if (state == "l_found") {
        state = "printing"
        print line_q
        print line_r
        print line_l
        line = 0
    } else if (state != "printing") {
        state = "idle"
    }
}

/^[0-9]+[[:space:]]+/ {
    # If in state "printing", print 50 lines then stop printing
    if (state == "printing") {
        if (++line < 48) print
    }
}
于 2012-10-04T18:44:11.733 に答える