以下のようなスペース区切りのファイル「test.txt」から、2列目の値が5以下の行を抽出することを考えます。
a 1 100 b 2 200 c 3 300 d 4 400 e 5 500 f 6 600 g 7 700 h 8 800 i 9 900 j 10 1000
このような問題に対しては、linux環境でawk(オーク)を利用すると手軽に実現できます。Bash等で下記のようなシェルスクリプト「awk.sh」を作成します。もちろん、他のSHELLを用いても構いません。入力するテキストファイルを「file」パラメータに、閾値を「param」パラメータに与えています。閾値paramのawk文への与え方がポイントになります。
#!/usr/bin/env bash
#
file=$1
param=$2
#
cat ${file} | awk '{if ($2 <= threshold) print}' threshold=${param}
プログラムawk.sh中のfileにtest.txtを、paramに5を指定して実行します。
$ ./awk.sh test.txt 5
a 1 100
b 2 200
c 3 300
d 4 400
e 5 500
2列目の値が5以下の行のみを抽出することができました。なお、awk文中の「$2」は、test.txtの2列目を意味します(paramの$2とは関係ありません)。
タブ区切りのファイル「test.tsv」に対してはどうでしょうか。
a 1 100 b 2 200 c 3 300 d 4 400 e 5 500 f 6 600 g 7 700 h 8 800 i 9 900 j 10 1000
awkではスペース区切りとタブ区切りのファイルを同様に扱うことができます。
$ ./awk.sh test.tsv 5
a 1 100
b 2 200
c 3 300
d 4 400
e 5 500
では、コンマ区切りのファイルに対してはどうでしょうか。
a,1,100 b,2,200 c,3,300 d,4,400 e,5,500 f,6,600 g,7,700 h,8,800 i,9,900 j,10,1000
この場合、スペース区切りやタブ区切りのファイルに使ったawk.shではうまく行きません。いくつかの対応方法がありますが、手っ取り早いのは「-F」オプションに「,」を指定することです。CSVファイル用awkである「awk_csv.sh」は以下になります。
#!/usr/bin/env bash
#
file=$1
param=$2
#
cat ${file} | awk -F, '{if ($2 <= threshold) print}' threshold=${param}
上記のawk_csv.shによりカンマ区切りのファイルtest.csvの処理が可能になりました。
$ ./awk_csv.sh test.csv 5 a,1,100 b,2,200 c,3,300 d,4,400 e,5,500
もし1列目と3列目のみを出力し、2列目を出力したくない場合には、以下のような「awk_csv_13.sh」を作成します。
#!/usr/bin/env bash
#
file=$1
param=$2
#
cat ${file} | awk -F, '{if ($2 <= threshold) print $1,$3}' threshold=${param}
上記のawk_csv_13.shを用いると以下のような結果になります。
$ ./awk.sh test.csv 5 a 100 b 200 c 300 d 400 e 500
結果はスペース区切りで出力されます。もしカンマ区切りで出力したい場合は、「-v」オプションを使ってOFSにカンマを与える方法が良さそうです。これを「awk_csv_13_ofs.sh」とします(ソースコードは改行しません)。
#!/usr/bin/env bash
#
file=$1
param=$2
#
cat ${file} | awk -F, -v 'OFS=,' '{if ($2 <= threshold) print $1,$3}' threshold=${param}
上記のawk_csv_13_ofs.shを使って実行してみます。
$ ./awk.sh test.csv 5 a,100 b,200 c,300 d,400 e,500
うまく行ったようです。今回説明したやり方を応用することで、結構色々な処理ができるようになりますよ。