01 / 07
これまでできなかった2つのこと
この章で困ったことを思い出してみて。
1. cut は空白の幅がそろっていないと崩れる
2. 合計や平均が出せない
点数の列を抜くことはできても、足し算はできなかったよね。sort も uniq も、数を並べたり数えたりはできるけれど、計算はできないんだ。
awk はその両方を解決するよ。列を扱うことに特化した、小さなプログラミング言語なんだ。
テキストを整形する
INPUT · スライド
01 / 07
この章で困ったことを思い出してみて。
1. cut は空白の幅がそろっていないと崩れる
2. 合計や平均が出せない
点数の列を抜くことはできても、足し算はできなかったよね。sort も uniq も、数を並べたり数えたりはできるけれど、計算はできないんだ。
awk はその両方を解決するよ。列を扱うことに特化した、小さなプログラミング言語なんだ。
02 / 07
awk のいちばん基本の形はこれだよ。
```
awk '{print $2}' sukima.txt
```
$1 が1列目、$2 が2列目……という意味だね。$0 は行全体だよ。
{} の中に「各行で何をするか」を書くんだ。awk はファイルを1行ずつ読んで、行ごとに {} の中を実行するよ。
そして空白の幅を気にしない。tanaka 80 でも suzuki 95 でも、$2 はちゃんと点数になるんだ。ここが cut との大きな違いだよ。
~ $ awk '{print $2}' sukima.txt80957203 / 07
CSV のようにカンマ区切りなら -F で指定するよ(field separator の F だね)。
```
awk -F, '{print $1}' seiseki.csv
```
cut -d に当たるものだね。名前が違うだけで役目は同じだよ。
列を入れかえられるのも cut との違いだよ。
```
awk -F, '{print $2, $1}' seiseki.csv # 80 tanaka
awk -F, '{print $3 "," $1}' seiseki.csv # 3,tanaka
```
print にカンマで並べると空白でつながり、"," を挟むとカンマでつながるよ。cut -f2,1 が効かなかったのを覚えているかな。awk なら自由だよ。
04 / 07
awk は便利な値を用意してくれているよ。
| 名前 | 意味 |
| --- | --- |
| NR | いま何行目か(Number of Records) |
| NF | この行に列がいくつあるか(Number of Fields) |
| $NF | 最後の列 |
```
awk '{print NR, $1}' sukima.txt # 行番号を振る
awk '{print $NF}' access.log # 最後の列だけ
```
$NF は覚えておくと便利だよ。列の数が行によって違うデータでも、最後の列は取り出せるからね。
NR を使えば nl の代わりにもなるね。同じことが何通りもの道具でできるのは、もう見慣れたね。
05 / 07
{} の前に条件を書くと、当てはまる行だけを処理するよ。
```
awk -F, '$2 > 80 {print $1}' seiseki.csv # 80点より上の人の名前
awk -F, '$1 == "sato" {print $2}' seiseki.csv
awk -F, '/tanaka/ {print $2}' seiseki.csv # tanaka を含む行
awk -F, 'NR == 2 {print $1}' seiseki.csv # 2行目
```
grep を超えているのに気づいたかな。grep は文字として探すことしかできなかったけれど、awk は「2列目が80より大きい」という数の比較ができるんだ。
{print} を省くと「行全体を出す」になるよ。だから awk -F, '$2 > 80' seiseki.csv だけで絞り込みができるんだ。
06 / 07
これが awk のいちばんの値打ちだよ。合計が出せるんだ。
```
awk -F, '{sum += $2} END {print sum}' seiseki.csv
```
読み方はこうだよ。
{sum += $2} … 各行で sum に2列目を足していくEND {print sum} … 全部の行を読み終わったあとに sum を出すEND は「最後に1回だけやること」を書く場所だよ。逆に BEGIN は「始める前に1回だけ」だね(見出し行を付けるときに使うよ)。
平均も出せるよ。NR が行数になっているからね。
```
awk -F, '{sum += $2} END {print sum/NR}' seiseki.csv
```
sum を用意する宣言が要らないのに気づいたかな。awk では使い始めた変数は自動で 0 から始まるんだ。
07 / 07
ファイルは3つだよ。
seiseki.csv … 名前,点数,順位 が3行sukima.txt … tanaka 80 のように空白の幅がバラバラaccess.log … 住所 方法 パス 結果 が3行(本物のログを小さくしたもの)シングルクォートで囲むのを忘れないでね。$ はシェルにとっても特別な文字なので、囲まないと $1 が消えてしまうんだ。
awk は奥が深くて、これだけで本が書ける道具だよ。この回で扱うのは列の取り出しと計算だけ。それでも日々の仕事のほとんどは足りるよ。