テキストを整形する

INPUT · スライド

列を計算する(`awk`)

01 / 07

これまでできなかった2つのこと

この章で困ったことを思い出してみて。

1. cut は空白の幅がそろっていないと崩れる
2. 合計や平均が出せない

点数の列を抜くことはできても、足し算はできなかったよね。sortuniq も、数を並べたり数えたりはできるけれど、計算はできないんだ。

awk はその両方を解決するよ。列を扱うことに特化した、小さなプログラミング言語なんだ。

02 / 07

$1 $2 が列を表す

awk のいちばん基本の形はこれだよ。

awk '{print $2}' sukima.txt

$1 が1列目、$2 が2列目……という意味だね。$0行全体だよ。

{} の中に「各行で何をするか」を書くんだ。awk はファイルを1行ずつ読んで、行ごとに {} の中を実行するよ。

そして空白の幅を気にしないtanaka 80 でも suzuki 95 でも、$2 はちゃんと点数になるんだ。ここが cut との大きな違いだよ。

~ $ awk '{print $2}' sukima.txt809572

03 / 07

区切りを変えるのは -F

CSV のようにカンマ区切りなら -F で指定するよ(field separator の F だね)。

awk -F, '{print $1}' seiseki.csv

cut -d に当たるものだね。名前が違うだけで役目は同じだよ。

列を入れかえられるのも cut との違いだよ。

awk -F, '{print $2, $1}' seiseki.csv     # 80 tanakaawk -F, '{print $3 "," $1}' seiseki.csv  # 3,tanaka

print にカンマで並べると空白でつながり、"," を挟むとカンマでつながるよ。cut -f2,1 が効かなかったのを覚えているかな。awk なら自由だよ。

04 / 07

NRNF — 番号と列数

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.csvawk -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

END で合計を出す

これが 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.txttanaka 80 のように空白の幅がバラバラ
  • access.log住所 方法 パス 結果 が3行(本物のログを小さくしたもの)

シングルクォートで囲むのを忘れないでね。$ はシェルにとっても特別な文字なので、囲まないと $1 が消えてしまうんだ。

awk は奥が深くて、これだけで本が書ける道具だよ。この回で扱うのは列の取り出しと計算だけ。それでも日々の仕事のほとんどは足りるよ。