2

以下に示す抜粋のようなファイルを取得し、一致する各レコードから特定の行 (たとえば、"Time (UTC):" で始まる行) を出力する効率的な awk スクリプトを作成したいと考えています。これを行うには、過去に行ったことよりも優れた方法があると思います。

サンプル ファイル (申し訳ありませんが、コード ボックスに空白行を挿入する方法がわかりません。空白行は "BLANK LINE" で表されます):

Processor: Some_Proc
Capsule abortion no 32
Time (UTC): Fri Jun 15 06:25:10 2012
CapsuleId: 1704167
CapsuleName: SomeAppProc
Reason: Assertion "Reason1"  
BLANK LINE
Processor: Some_Proc
Capsule abortion no 33
Time (UTC): Fri Jun 15 06:25:10 2012
CapsuleId: 1704168
CapsuleName: SomeAppProc
Reason: Assertion "Reason2"  
BLANK LINE
Processor: Some_Proc
Capsule abortion no 34
Time (UTC): Fri Jun 15 06:25:10 2012
CapsuleId: 1704168
CapsuleName: SomeAppProc
Reason: Assertion "Reason1"

前のコード例 (申し訳ありませんが、このフォーラムでインデントを保持する方法がわかりません。8 つのスペースを試しましたが、うまくいきませんでした)

BEGIN {
    RS=""  #Each record is a "paragraph"
    FS="\n" #Each field is a line
}

/Reason1/ {
    # print $3  would work if it always shows up on the third line
    # but the following for loop should find it if it's on a different line
    for (i=1;i<=NF;i++) {
        if ($i ~ /^Time.*/) {
            print $i
            next
        }
    }
} 

常に同じ順序で発生しない場合、行を印刷するより効率的な方法はありますか?

ありがとう

4

2 に答える 2

1

それは私にとって良い解決策のようです。私は問題に対して同じアプローチを使用したでしょう。行が見つかったらループを停止したいので、break代わりに使用します。next命令がループの次のサイクルを実行するため、next命令はほとんど意味がありません。

for (i=1;i<=NF;i++) {
    if ($i ~ /^Time.*/) {
        print $i
        break
    }
}
于 2012-07-10T17:38:12.080 に答える
1

このようなものはどうですか?:

BEGIN { reset(); }
END { reset(); }
$0 == "" { reset(); }
/^Reason:/ && $3 == "\"Reason1\"" { found = 1; }
/^Time \(UTC\):/ { time = $0; }

function reset() {
  if (found) { print time; }
  found = 0;
  time = "(unknown)";
}

そして、改行のデフォルトのレコード区切り記号を使用します。これが行うことは、読み取られた時間と理由のフィールドに注意し、一致する各レコードの最後に時間を出力することです。

于 2012-07-10T22:51:29.150 に答える