setは置換、grepは検索、awkは列の抽出が得意としているので、この3つを組み合わせてゴニョゴニョすれば大抵のこと事足りる、と思っています。
今回はawkコマンドの基本操作を抑えていきましょう。
基本中の基本の型はこちらです。
awk ‘パターン {アクション}’
文字列を抽出する
スペース区切りのサンプルファイルを用意しました。
$ cat sample.txt
Apple 5.00 12
Banana 3.34 5
Kiwi 2.87 15
Pineapple 6.02 3
1番目フィールドを抽出するときは$1, 2番目は$2, 3番目は$3と指定します。
全ての列を抽出するときは$0を指定します。
# 1番目と2番目のフィールドを抽出します
$ awk '{print $1,$2}' sample.txt
Apple 5.00
Banana 3.34
Kiwi 2.87
Pineapple 6.02
# 全てのフィールドを抽出します
$ awk '{print $0}' sample.txt
Apple 5.00 12
Banana 3.34 5
Kiwi 2.87 15
Pineapple 6.02 3
抽出条件を与える
条件に一致する行のフィールドを抽出します。
条件が複数ある場合は、AND演算子「&&」やOR演算子「||」で繋いで行きます。
条件式の部分を()で括ってもいいですし、括らなくてもOKです。
また、全てのフィールドを抽出する場合は、アクションの記述を省略することがきます。
# 3番目のフィールドの数字が10より大きい場合、全てのフィールドを抽出する
$ awk '$3 > 10 {print $0}' sample.txt
Apple 5.00 12
Kiwi 2.87 15
# 3番目のフィールドの数字が10より大きく、かつ1番目のフィールドかAppleではない場合、全てのフィールドを抽出する
$ awk '($3 > 10 && $1 != "Apple") {print $0}' sample.txt
Kiwi 2.87 15
$ awk '$3 > 10 && $1 != "Apple" {print $0}' sample.txt
Kiwi 2.87 15
# アクションの記述を省略した書き方
$ awk '$3 > 10 && $1 != "Apple"' sample.txt
Kiwi 2.87 15
抽出したフィールド(列)を計算につかう
抽出した数値を計算に使用し、その結果を出力させます
# 1番目のフィールドと2番目のフィールドを掛けた結果を出力させます
$ awk '{print $1, $2*$3}' sample.txt
Apple 60
Banana 16.7
Kiwi 43.05
Pineapple 18.06
複数のファイルに対してawkコマンドをつかう
こちらも簡単、複数のファイルを指定してやるだけです。
sample2.txtというファイルを用意しました。
sample.txtとsample2.txtから1番目と2番目の列を抽出します。
$ cat sample2.txt
Orange 3.00 20
Strawberry 1.00 50
# sample.txtとsample2.txtから1番目と2番目のフィールドを抽出
$ awk '{print $1,$2}' sample.txt sample2.txt
Apple 5.00
Banana 3.34
Kiwi 2.87
Pineapple 6.02
Orange 3.00
Strawberry 1.00
最後のフィールド(列)を抽出する:NF変数
各行によってフィールド数が異なっていたり、そもそもフィールド数が分からない(目視で数えるのは無理)というような場合があります。こうゆうときNF変数が便利です。
こうゆうサンプルを用意しました。
$ cat sample3.txt
0 0 0 0 0 1 10
0 0 0 0 0 0 2 20
0 0 0 0 0 0 0 3 30
「$NF」で最後のフィールドを指定できます。
また、紛らわしいですが「NF」とするとフィールド数を表します。
# 最後のフィールドを表示する
$ awk '{print $NF}' sample3.txt
10
20
30
# 最後から2番目のフィールドを表示する
$ awk '{print $(NF-1)}' sample3.txt
1
2
3
# 最後のフィールドの値から1引いた数を表示する
$ awk '{print $NF-1}' sample3.txt
9
19
29
# 各行のフィールド数を表示する
$ awk '{print NF}' sample3.txt
7
8
9
# 各行のフィールド数から1引いた数を表示する
$ awk '{print NF-1}' sample3.txt
6
7
8
# フィールド数が8個より大きい行の全フィールドを表示する
$ awk 'NF > 8' sample3.txt
0 0 0 0 0 0 0 3 30
紛らわしいですね。注意してくださいね。
区切り文字を指定する
区切り文字を指定しない場合は、「スペース」と「タブ」両方の区切りとなります。
下記のようなサンプルファイルを用意しました。
1行の中に「スペース」「:」「,」「タブ(TAB Insertの前)」が含まれています。
区切り文字を指定して抽出してみましょう
$ cat split.txt
$1:Mac Baseball,7000,AA TAB Insetrt
$2:Mary Tennis,5000,AB TAB Insetrt
$3:Dan Football,8700,BB TAB Insetrt
「,」「:」「タブ」で区切った場合の2番目のフィールドを抽出する。
# カンマ区切りの第2フィールドを抽出する
$ awk -F, '{print $2}' split.txt
7000
5000
8700
$ awk -F "," '{print $2}' split.txt # この書き方でもOK
7000
5000
8700
# コロン区切りの第2フィールドを抽出する
$ awk -F: '{print $2}' split.txt
Mac Baseball,7000,AA TAB Insetrt
Mary Tennis,5000,AB TAB Insetrt
Dan Football,8700,BB TAB Insetrt
$ awk -F ":" '{print $2}' split.txt # この書き方でもOK
Mac Baseball,7000,AA TAB Insetrt
Mary Tennis,5000,AB TAB Insetrt
Dan Football,8700,BB TAB Insetrt
# タブ区切りの第2フィールドを抽出する
$ awk -F\t '{print $2}' split.txt
TAB Insetrt
TAB Insetrt
TAB Insetrt
$ awk -F "\t" '{print $2}' split.txt
TAB Insetrt
TAB Insetrt
TAB Insetrt
複数の区切り文字を指定する
「:」と「,」の両方で区切ります。
$ awk -F [:,] '{print $2}' split.txt
Mac Baseball
Mary Tennis
Dan Football
printfを使ってフォーマット形式で表示する
printfを使って整形した文字列を表示することもできます。
こんなサンプルを用意しました。
$ cat sample4.txt
SATO,1200,25
TANAKA,1000,35
YAMADA,1600,40
名前、時給、勤務時間のcsvファイルです。
それぞれの給与を見やすく形成して表示してみましょう。
$ awk -F, '{printf("%-8s さんの今月の給与は %8.2f です。\n", $1, $2*$3)}' sample4.txt
SATO さんの今月の給与は 30000.00 です。
TANAKA さんの今月の給与は 35000.00 です。
YAMADA さんの今月の給与は 64000.00 です。
コメント