web-dev-qa-db-ja.com

awkを使用して、列内のWordの出現回数をカウントする

03/03/2014 12:31:21 BLOCK 10.1.34.1 11:22:33:44:55:66

03/03/2014 12:31:22 ALLOW 10.1.34.2 AA:BB:CC:DD:EE:FF

03/03/2014 12:31:25 BLOCK 10.1.34.1 55:66:77:88:99:AA

私はawkを使用して、1つのコマンドで上記の「ブロック」と「アクセス」の出現回数をカウントしようとしています。

最初にWordの「ブロック」を試しましたが、カウンターが機能していないようです。私のコードが間違っている場所を誰でも見ることができますか?

awk ' BEGIN {count=0;}  { if ($3 == "BLOCK") count+=1} end {print $count}' firewall.log
13
user3578872

配列を使用する

awk '{count[$3]++} END {for (Word in count) print Word, count[Word]}' file

具体的に「ブロック」したい場合:END {print count["BLOCK"]}

30
glenn jackman

これは非コードソリューションです。ステップをパイプ( "|")でつなげることができます。

awk '{print $3}' file | sort | uniq -c
  • awk '{print $ 3}'
    3列目を印刷します。awkのデフォルトのレコード区切り文字は空白です。

  • ソート
    結果を並べ替える

  • uniq -c
    繰り返し発生回数を数える

15
David Thornton

コードが機能しない理由はENDが大文字と小文字を区別するためです。スクリプトは変数endが存在するかどうかをチェックし(存在しない)、最後のブロックは実行されません。それを変更すれば、それは機能するはずです。

また、すべての変数が0でインスタンス化されるため、BEGINブロックは必要ありません。

以下に、代わりに使用したい別の方法を追加しました。

これはglennに似ていますが、必要な単語のみをキャプチャします。そのため、メモリをほとんど使用しないはずです。


Gawkの使用(一致の3番目の引数用)

awk 'match($3,/BLOCK|ALLOW/,b){a[b[0]]++}END{for(i in a)print i ,a[i]}' file

このブロックは、BLOCKまたはALLOWが3番目のフィールドに含まれている場合にのみ実行されます。
一致は、配列bに一致したものをキャプチャします。
次に、一致したフィールドの配列aがインクリメントされます。

ENDブロックでは、キャプチャされた各フィールドに発生回数が出力されます。


出力は

ALLOW 1
BLOCK 2
4
user4453924

あなたの声明をテストしました

awk ' BEGIN {count=0;}  { if ($3 == "BLOCK") count+=1} end {print $count}' firewall.log

2つの変更を行うことでBLOCKを正常にカウントできました

  1. endは大文字にする必要があります
  2. 削除する $ from print $count

したがって、次のようになります。

awk ' BEGIN {count=0;}  { if ($3 == "BLOCK") count+=1} END {print count}' firewall.log 

動作する簡単なステートメントは次のとおりです。

awk '($3 == "BLOCK") {count++ } END { print count }' firewall.log
3
psoo

awk呼び出しのエラーは、「END」ブロックにprint $count。それはcount変数の内容を受け取り、それが整数であると仮定し、入力の最後の行で対応するフィールドを見つけようとします。本当に欲しいのはprint countは、count変数の値を出力するだけです。 bashawkpythonなどの間で異なる変数参照スキームを混同するのは簡単な場合があるため、間違いを犯すのは簡単です。

1
twalberg