awkでファイル内の数を集計

awkコマンドでお手軽に計算をしてみましょう.

概要

awkコマンドで合計や平均を求める方法を説明します.

サンプルデータ

sar コマンドの結果↓を コマンドラインで解析してみましょう.

sar 1 > a.txt

として,a.txt を作りました.

ファイルの中身は こんな感じ↓です.

# head a.txt
Linux 5.15.26 (debian)  03/07/2022      _x86_64_        (8 CPU)

02:20:48 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
02:20:49 AM     all      0.52      0.00      9.41      1.55      0.00     88.53
02:20:50 AM     all      0.78      0.00      8.17      1.56      0.00     89.49
02:20:51 AM     all      0.88      0.00     10.34      1.01      0.00     87.77
02:20:52 AM     all      0.64      0.00     10.04      0.89      0.00     88.44
02:20:53 AM     all      1.39      0.00      9.25      1.27      0.00     88.09
02:20:54 AM     all      0.66      0.00      8.32      1.59      0.00     89.43
02:20:55 AM     all      1.04      0.00      8.43      1.43      0.00     89.11

478行のファイルです

# wc a.txt
  478  4291 38134 a.txt

全ての行を表示する

awk '{print}' < a.txt

で可能です.

実行例

# awk '{print}' < a.txt | head
Linux 5.15.26 (debian)  03/07/2022      _x86_64_        (8 CPU)

02:20:48 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
02:20:49 AM     all      0.52      0.00      9.41      1.55      0.00     88.53
02:20:50 AM     all      0.78      0.00      8.17      1.56      0.00     89.49
02:20:51 AM     all      0.88      0.00     10.34      1.01      0.00     87.77
02:20:52 AM     all      0.64      0.00     10.04      0.89      0.00     88.44
02:20:53 AM     all      1.39      0.00      9.25      1.27      0.00     88.09
02:20:54 AM     all      0.66      0.00      8.32      1.59      0.00     89.43
02:20:55 AM     all      1.04      0.00      8.43      1.43      0.00     89.11

CPU使用率が表示されている行のみを抽出する

awk '/[0-9]$/{print}' < a.txt

で可能です.

実行例

# awk '/[0-9]$/{print}' < a.txt | head
02:20:49 AM     all      0.52      0.00      9.41      1.55      0.00     88.53
02:20:50 AM     all      0.78      0.00      8.17      1.56      0.00     89.49
02:20:51 AM     all      0.88      0.00     10.34      1.01      0.00     87.77
02:20:52 AM     all      0.64      0.00     10.04      0.89      0.00     88.44
02:20:53 AM     all      1.39      0.00      9.25      1.27      0.00     88.09
02:20:54 AM     all      0.66      0.00      8.32      1.59      0.00     89.43
02:20:55 AM     all      1.04      0.00      8.43      1.43      0.00     89.11
02:20:57 AM     all      0.81      0.00      6.19      1.75      0.00     91.25
02:20:58 AM     all      0.79      0.00      7.74      2.49      0.00     88.98
02:20:59 AM     all      1.97      0.00      9.84      3.41      0.00     84.78

3行減ったので,475行です.

# awk '/[0-9]$/{print}' < a.txt | wc
    475    4275   38000

grepを用いても可能です

grep [0-9]$ a.txt

%usrの列のみ抽出する

awk '/[0-9]$/{print $4}' < a.txt

で,可能です.

実行例

# awk '/[0-9]$/{print $4}' < a.txt | head
0.52
0.78
0.88
0.64
1.39
0.66
1.04
0.81
0.79
1.97

%usrの列の値の合計を求める

awk '/[0-9]$/{SUM+=$4}END{print SUM}' < a.txt

で,可能です.

結果

awk '/[0-9]$/{SUM+=$4}END{print SUM}' < a.txt
34792.8

%usrの列の値の平均を求める

awk '/[0-9]$/{SUM+=$4;CNT++}END{print SUM/CNT}' < a.txt

で,可能です.

結果

# awk '/[0-9]$/{SUM+=$4;CNT++}END{print SUM/CNT}' < a.txt
73.2479

残念ながら,これ↓では不可能です.

awk '/[0-9]$/{SUM+=$4}END{print SUM/NR}' < a.txt

結果

# awk '/[0-9]$/{SUM+=$4}END{print SUM/NR}' < a.txt
72.7882
# awk '/[0-9]$/{SUM+=$4}END{print SUM/NR,NR}' < a.txt
72.7882 478

NRは読み込んだ行数.
/[0-9]$/にマッチしない最初の3行も読み込むので,475行でなく,478行です.

grepを用いた方が分かりやすいかも知れません.
マッチしない3行は,grepで先に削除され,awkに渡されない.

# grep [0-9]$ a.txt | awk '{SUM+=$4}END{print SUM/NR}'
73.2479
# grep [0-9]$ a.txt | awk '{SUM+=$4}END{print SUM/NR,NR}'
73.2479 475

「%usr列と%system列の値の和」の平均を求める

awk '/[0-9]$/{SUM+=$4+$6;CNT++}END{print SUM/CNT}' < a.txt

で,可能です.

結果

# awk '/[0-9]$/{SUM+=$4+$6;CNT++}END{print SUM/CNT}' < a.txt
89.2164

grepを用いた方が分かりやすいかも知れません.

# grep [0-9]$ a.txt | awk '{SUM+=$4+$6}END{print SUM/NR}'
89.2164

「%usr列の値と%system列の値の和」が50以上の行の数を数える

awk '/[0-9]$/{if($4+$6>=50){CNT++}}END{print CNT}' < a.txt

で可能.

実行結果

# awk '/[0-9]$/{SUM+=$4+$6;CNT++}END{print SUM/CNT}' < a.txt
89.2164

同様にgrepを用いた方が分かりやすいかも知れません.

# grep [0-9]$ a.txt | awk '$4+$6>=50{CNT++}END{print CNT}'
425

いいなと思ったら応援しよう!