はじめまして!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を是非活用していってください!
\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //