awkはsedのパイプ出力を処理できません。

awkはsedのパイプ出力を処理できません。

おおよそ次のログファイルがあります。

Sep 23 10:28:26 node kernel: em0: device is going DOWN
Sep 23 10:28:26 node kernel: em0: device is going UP
Sep 23 10:29:14 node cdsmon: /tmp/instance0 ; core dumped
Sep 23 10:29:14 node cdsmon: /tmp/instance0 ; core dumped
Sep 23 10:28:26 node kernel: em0: device is going DOWN
Sep 23 10:29:14 node cdsmon: /tmp/instance1 ; core dumped
Sep 23 10:28:26 node kernel: em0: device is going UP
Sep 23 10:29:14 node cdsmon: /tmp/instance2 ; core dumped

cdsmon行を検出してから行を分割したい(同様のイベントを;取得するため)/tmp/instance0core dumped

これを行うには、以下を使用しますsed

sed -u -n -e "s/^.*cdsmon: //p" /tmp/dev.log

出力は次のとおりです。

/tmp/instance0 ; core dumped
/tmp/instance0 ; core dumped
/tmp/instance1 ; core dumped
/tmp/instance2 ; core dumped

ただし、この出力をawk以下のように配管すると、上記と同じ出力が得られます。

sed -u -n -e "s/^.*cdsmon: //p" /tmp/dev.log | awk -F ";" "{print $1}"

-uオプションを削除したにもかかわらず、同じ状況が観察されましたsed

私が何かを見逃しているなら、誰かがそれを指摘することができますか?私は通常のawk / sedでFreeBSDボックスを使用していますが、残念ながら新しいパッケージをインストールすることはできません。

ベストアンサー1

この動作の理由は、awkプログラムが次に含まれているためです。ダブル引用符は、文字列をシェルの変数拡張に公開するようにします。これは、プログラムを実行するシェルが最初に展開され、$1それが定義されていない可能性があるため、空の文字列に展開されることを意味します。

したがって、あなたのプログラムは次のようになります。

awk -F ";" "{print}"

これがライン全体が印刷される理由です。これは常にawk(と)プログラムですsed一つ引用符。

sedほとんどの場合、出力をパイプに接続したり、awkその逆にパイプする必要はありません。あなたの例では、「イベントタグ」の後の最初のフィールドを取得するには、次のようにします。

sed -E -n 's/^.*cdsmon: ([^;]*).*$/\1/p' /tmp/dev.log 

これは以下を定義します。キャプチャグループcdsmon:最初の文字列の後に文字列を囲み、行;全体をそのキャプチャグループの内容に置き換えます。

記録されたイベントの概要を印刷するには、上記の方法を次のように拡張cdsmonできます。sed

sed -E -n 's/^.*cdsmon: ([^;]*) ; (.*)$/\1 : \2/p' dev.log 

または別のawk唯一のアプローチがあります。

awk -F'(cdsmon: | ; )' 'NF==3{printf "%s : %s\n",$2,$3}' dev.log 

あなたの例は、両方印刷されます

/tmp/instance0 : core dumped
/tmp/instance0 : core dumped
/tmp/instance1 : core dumped
/tmp/instance2 : core dumped

ただし、このawk方法では極端なケースが発生する可能性があります。パターンcdsmon: ;フィールドの区切り記号を使用してください。 3つのフィールドがある場合(例では、エントリでのみ発生する場合cdsmon:)、afterインスタンス名cdsmon:とafter理由に対応する2番目と3番目のフィールドを印刷します;

おすすめ記事