AWK Simple プログラムは、値の最大発生回数を見つけると予想とは異なる動作をします。

AWK Simple プログラムは、値の最大発生回数を見つけると予想とは異なる動作をします。

ログファイルで最もよく見られるIPアドレスを見つける単純なawkプログラムip.awkがあります。 IPアドレスは最初の列にあります。

$cat ip.awk

{ ip[$1]++ }
END {
for (i in ip)
        if ( max < ip[i] ) {
                max = ip[i]
                maxnumber = i }
print maxnumber, " has accessed ", max, " times.", " $1 is: ", $1 }

私はこれをaccess.logファイルを解析するために使用します。このファイルの一部のサンプル項目は次のとおりです。

173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.2.1 HTTP/1.1" 200 7404 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/themes/twentytwelve/js/navigation.js?ver=20140711 HTTP/1.1" 200 1720 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/uploads/2013/11/tailshadow.png HTTP/1.1" 200 11433 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/uploads/2014/05/cropped-wp3.png HTTP/1.1" 200 65326 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/?p=2407 HTTP/1.1" 200 21717 "https://www.google.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"

私はawkスクリプトが以下を正しく提供すると思います。

$awk -f ip.awk access.log 
68.107.81.110  has accessed  311  times.  $1 is:  70.168.57.66

私の混乱は$ 1の値に関連していますが、awkがログファイルaccess.logを介してその行の最初の列の値に移動するにつれて、この値は1行ずつ変更する必要があることを理解しています。

これは、最後の行のIPアドレスを返すからです(ログファイルには30000行を超えるため、これを確認するプログラムを作成しました)。それは実際に動作しますか?

$cat testfile.log 
1   apple
2   banana
2   banana
3
3
3
4
4
4
4
5
5   flerb
5   flerb
5   flerb
5   flerb
5   flerb , green - tea
6
7
8   grapes 0 and some more filler to make a long line
9

ところで、こうすると正解が出ますが、印刷してみると1ドルに「9」という値が出ません。私は何を見逃していますか?

$awk -f ip.awk testfile.log 
5  has accessed  6  times.  $1 is: 

別の変数を取り除くために、ipアドレスの最初の列を新しいファイルに別々に作成し、そこでip.awkを実行しました。また、ドットで区切られた10進数のIPアドレスが配列でどのように機能するかについての基本的な内容がありません。さらに:1.0 2.0...を1 2に使用すると...まだ正解を得ることができますが、まだ$ 1の値ではありません。

回答:thecarpyが提案したように、問題はテストファイルに値を入力したときに最後の値の後にEnterキーを押すと追加の改行が追加され、その行を解析するときに$ 1が空の文字列に設定されることです。

答え1

プログラムからawkすべてのデータを読み取るとENDブロックが実行されるため、解析する入力行はありません。 (一部の実装では、最後の行の最初のフィールドとしてawk予約されていることがわかります。$1AWK ENDアクションがマニュアルページの$ 0に最後の行をロードするかどうか.)

awk連想配列を使用します。これは、すべての文字列をインデックスとして使用できることを意味します。数値配列が機能する理由は、配列の添字が単一文字の文字列であるa[1]ためです。それは等しくても偶数でもかまいません。 IP アドレスの破線の四角形は単純な文字列です。a[]1a[one]a[banana]

関連情報