株式会社クイックのWebサービス開発blog

HAPPYなサービスプランナー・エンジニア・デザイナーのブログです。

awkで作業効率アップ!

はじめまして!2020年6月に中途入社したソフトウェアエンジニアのたろーです!

皆さん、CSVやTSV形式のファイルの操作をする際にどのようなツールを使ってますか?
テキストエディタExcelスプレッドシート 、拡張子毎の専用エディタなどなど色々な方法があると思います。

でも、 「簡単な集計程度であればわざわざツールでファイル開いて関数とかフィルタを組み込んでいくような作業したくないな〜」 なんて思うことありませんか???

そこで今回僕から推したいのはかの有名なawkです!

普段CLIで作業を行っていなかったり、サーバサイドの開発をあまり行わなかったり、awkを使ったことない方からすると、
「サーバサイドエンジニアが使ってるのよく見るけど使ったことない…」 「名前はよく聞くけどなんとなく難しそう…」「よくわからないけど怖い」
のようにとっつきにくいイメージがあるんじゃないでしょうか?

ですが実際は簡単なお作法さえ覚えてしまえばとてもお手軽で便利なので、 今回は布教活動の一環として初めの1歩的な使い方を紹介したいと思います!

awkとは?

awkはテキストの加工や抽出が得意なプログラム言語です。
for文などのループ処理を書かずにファイルの行ごとの処理が行えます!
ほとんどのLinux系OSやmacOS等にも標準で入っているので導入も簡単です!

awk '実行スクリプト' 処理対象ファイル

のような形式で簡単にターミナルから実行できちゃいます。

実行スクリプトをファイルに記述している場合は

awk -f 実行スクリプトファイル 処理対象ファイル

のように-fで実行スクリプトファイルを指定することで実行可能です。

実際に使ってみましょう

まずは今回使うサンプルCSVです。 架空のテストの採点結果をCSVで出力しています。

受験者名 所在地 点数(数学) 点数(国語)
tanaka tokyo 100 100
yamada saitama 90 50
sato chiba 80 90
suzuki kanagawa 70 60
saito kanagawa 85 95
yamamoto saitama 88 75
kitano tokyo 90 95

生のファイルだとこのような感じです。
sample.csv

tanaka,tokyo,100,100
yamada,saiatama,90,50
sato,chiba,80,90
suzuki,kanagawa,70,60
saito,kanagawa,85,95
yamamoto,saitama,88,75
kitano,tokyo,90,95

ファイルの内容全てを出力したい

$ awk '{print $0}' sample.csv

print $nでn番目の列のデータを指定し表示できます。$0だと全ての列 を指定します。
でもファイルの内容表示だけであればcatを使った方が早いですね!

特定の列のみを出力したい

コマンド

$ awk -F, '{OFS=","}{print $1,$2}' sample.csv

出力結果

tanaka,tokyo
yamada,saiatama
sato,chiba
suzuki,kanagawa
saito,kanagawa
yamamoto,saitama
kitano,tokyo

-Fオプションで読み込みファイルのデリミタ、OFS=","で出力用のデリミタを指定が可能です。
今回はCSVなので入出力のデリミタにカンマを指定し、1列目の受験者名と2列目の所在地を出力しています。
このレベルでの使い方であればcutコマンドでも行えますが、

$ cut -d, -f1,2 sample.csv

デリミタの指定と指定列の抽出はawkの肝となるところなので是非覚えてください!

指定列の合計値をデータ毎に出力したい

コマンド

$ awk -F, '{OFS=","}{print $0,$3+$4}' sample.csv

出力結果

tanaka,tokyo,100,100 200
yamada,saiatama,90,50 140
sato,chiba,80,90 170
suzuki,kanagawa,70,60 130
saito,kanagawa,85,95 180
yamamoto,saitama,88,75 163
kitano,tokyo,90,95 185

awk感(?)でてきましたね!
5列目に数学と国語の合計点の列が追加されています!
$0,$3+$4で既存の情報の後ろに合計点を演算して出力しています。
わざわざExcel開いてsum関数を挿入していかなくても簡単に演算が行えるんです!

CSVに論理名のヘッダーを付与して、更にデータ毎に採番したい。

コマンド

$ awk -F, 'BEGIN{OFS=",";print"No","受験者名","所在地","点数(数学)","点数(国語)","点数(合計)"} {print NR,$0,$3+$4}' sample.csv

出力結果

No,受験者名,所在地,点数(数学),点数(国語),点数(合計)
1,tanaka,tokyo,100,100,200
2,yamada,saiatama,90,50,140
3,sato,chiba,80,90,170
4,suzuki,kanagawa,70,60,130
5,saito,kanagawa,85,95,180
6,yamamoto,saitama,88,75,163
7,kitano,tokyo,90,95,185

やりたいこと2つ盛り合わせです!
BEGIN{処理}で、行毎の処理を行う前に実行する処理が指定できます。今回は出力用デリミタの指定とヘッダ情報の出力を行っています。
次にprint NRで各行にデータ番号を出力しています。NRは用意されている組み込み変数で、処理中の行数が格納されています。
Excelで各行に番号をふる作業とはサヨナラですね!

平均値を出力したい

コマンド

$ awk -F, '{mSum+=$3;jSum+=$4} END{printf("数学%d点 国語%d点\n",mSum/NR,jSum/NR)}' sample.csv

出力結果

数学86点 国語80点

END{処理}で行毎の処理が終わった後に行う処理を指定することができます!
行毎の処理で数学と国語の点数を加算し積み上げ、
ENDブロックでは合計点を行数(NR)で除算することで平均を算出、printfを用いて整数値フォーマットを指定して出力しています。

指定列が一定の数値以上のデータのみ出力したい

コマンド

$ awk -F, '$4>=80{print $0}' sample.csv

出力結果

tanaka,tokyo,100,100
sato,chiba,80,90
saito,kanagawa,85,95
kitano,tokyo,90,95

4列目、国語の点数が80点以上のデータのみ抽出しています。
パターン{処理}でパターンにマッチしたときのみ処理をおこなっています。今回は数値の比較演算を用いましたが正規表現パターンによるマッチも可能です。
また、処理内にif文を記述することでも同様の処理を行えます!

$ awk -F, '{if($4>80){print $0}}' sample.csv

もちろんelse句も使えるので条件に応じてデータの出しわけも可能です!

$ awk -F, 'BEGIN{OFS=","}{if($4>=80){result="OK"}else{result="NG"};print $1,result}' sample.csv

出力結果

tanaka,OK
yamada,NG
sato,OK
suzuki,NG
saito,OK
yamamoto,NG
kitano,OK

指定列の合計値をデータ毎に出力し、合計値の降順でデータを並び変えたい

コマンド

$ awk -F, '{OFS=","}{print $0,$3+$4}' sample.csv | sort -t, -n -r -k5

出力結果

tanaka,tokyo,100,100,200
kitano,tokyo,90,95,185
saito,kanagawa,85,95,180
sato,chiba,80,90,170
yamamoto,saitama,88,75,163
yamada,saiatama,90,50,140
suzuki,kanagawa,70,60,130

他コマンドとの合わせ技です!5列目に数学と国語の点数の合計値の出力を行った後に、sortコマンドで並び替えています。
sortコマンドでは-tオプションでデリミタの指定、-nオプションで数値ソート指定、-rで降順指定、-kオプションで並び替え評価対象の列指定を行っています。
awkコマンド単体でもソートは行えるのですが、他のコマンドと組み合わせることでより簡単にやりたいことを実現できます!

最後に

基本の部分(とちょっとだけ応用)の使い方のみの紹介でしたが、思ったより簡単に色々なことができそうだと感じていただけたのではないでしょうか!?
他にもawkに用意されている関数を使ったり他のコマンドと組み合わせることで本当に色々なことがCLI上から行えます!
普段当たり前のようにExcelやファイルエディタでファイルを開いて行っていた作業が、コマンド1つで行えるのは作業効率アップにもつながりますね!

一見怖そうだけど実は優しい先輩コマンド(言語)代表のawkを是非活用していってください!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp