LoginSignup
3
0

awkコマンドで2列のgroup by集計

Last updated at Posted at 2023-12-17

はじめに

apacheログで「特定のURLパス」の「時間帯」ごとのレスポンス速度を集計する際に、シェルスクリプトのawkコマンドを使って、2列のgroup by集計が必要になったので、やり方を備忘録として残します。

結論

group byしたい2列を文字列結合して集計するだけ。
(※あとで更に修正しやすいように、集計後に再度列を分割して出力を推奨)

下記のようなログデータがあるとする。

apache.log
20231218-112000 /users 2
20231218-113000 /categories 3
20231218-114000 /users 5
20231218-115000 /categories 1
20231218-121000 /categories 4
20231218-122000 /users 8
20231218-123000 /users 2
20231218-124000 /categories 7

※日時 URLパス レスポンス時間(秒)
※日時は20231218-112000 = 2023年12月18日11時20分00秒の意味

このデータをもとに、下記のような「各パス」の「時間帯」ごとの「平均レスポンス時間(秒)」を集計したい。

/categories 11 2 ※11時台は平均2秒のレスポンス時間
/categories 12 5.5
/users 11 3.5
/users 12 5

ステップ1

group byしたい2列を文字列結合して出力。

#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' # $1:日時, $2:URLパス, $3:レスポンス時間(秒)

# ↓出力結果
11/users 2
11/categories 3
11/users 5
11/categories 1
12/categories 4
12/users 8
12/users 2
12/categories 7

awk '{print $1$2}' と、カンマで区切らず書くことで、列を文字列結合できる。
上記例では、「時間帯」だけ必要だったので、substr($1, 10, 2)で時間を抽出したうえで$2(パス)と結合させている

ステップ2

ステップ1の出力をもとに集計する。

#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' | # $1:日時, $2:URLパス, $3:レスポンス時間(秒)
awk '{count[$1]++; sum[$1]+=$2} END{for(i in count) print i, sum[i]/count[i]}' # $1:時間+URLパス, $2:レスポンス時間(秒)

# ↓出力結果
11/categories 2
12/users 5
12/categories 5.5
11/users 3.5

ステップ3

使いやすい&見やすいように、列を分割、列の並び順を整理し、行もソートする。

#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' |
awk '{count[$1]++; sum[$1]+=$2} END{for(i in count) print i, sum[i]/count[i]}' |
awk '{print substr($1, 3), substr($1, 1, 2), $2}' |
sort -k1 -k2 # 1列目、2列目でソート

# ↓出力結果
/categories 11 2
/categories 12 5.5
/users 11 3.5
/users 12 5

完成🎉🎉🎉

ステップ4(おまけ)

スプレッドシートなどに貼り付けやすいように加工する。

#!bin/zsh
cat apache.log |
awk '{print substr($1, 10, 2)$2, $3}' |
awk '{count[$1]++; sum[$1]+=$2} END{for(i in count) print i, sum[i]/count[i]}' |
awk '{print substr($1, 3)"\t", substr($1, 1, 2)"\t", $2}' |
sort -k1 -k2 | tee >(pbcopy)

# ↓出力結果
/categories      11      2
/categories      12      5.5
/users   11      3.5
/users   12      5

"\t"を挟んで、タブ区切りにする。
tee >(pbcopy)で標準出力を確認しつつ、クリップボードにもコピー。

コピーされた内容をスプレッドシートにそのまま貼り付けると、表として綺麗に貼り付けできる(下図)
image.png

おわりに

awkコマンドを活用することで、テキストログから有用な情報を抽出できます。
是非活用してみてください!!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0