MAGAZINE
ルーターマガジン
知ってると得するAWKの書き方9選
アルバイトのMoriです。
今回は業務で触れる機会があり、プライベートでも使い始めた言語AWKについて書かせていただきました。
目次
- なにを紹介するのか
- 1. 最後からn番目の列を出力する
- 2. ファイルの2行目以降だけ扱う
- 3. コマンドラインから引数を与える
- 4. 区切り文字を複数指定する
- 5 パターンマッチに変数を使用する
- 6. CSV形式で出力する
- 7. ファイルを読み込む
- 8. 合計・平均・分散・標準偏差を求める
- 9. 相関係数を求める
- 最後に
- 参考にしたWebページ
なにを紹介するのか
awkを書いているとき「これってどう書くんだろう?」と手をとめて考えてしまう処理をピックアップしてまとめてみました
1. 最後からn番目の列を出力する
組み込み変数NF
を用いれば良い。
awk '{ print $(NF-n+1) }'
例
最後から2番目の値を出力する場合
$ echo "a b c d" | awk '{ print $(NF-1) }'
c
2. ファイルの2行目以降だけ扱いたい
組み込み変数FNR
とパターンマッチングを用いれば良い
awk 'FNR > 1 { なにかしらの処理 }'
例
以下のようなCSVhuga.csv
の1列目(1行目を除く)を取得する場合
name,age,gender
Tom,18,male
Alice,20,female
Watson,45,male
$ awk -F',' 'FNR > 1 { print $1 }' fuga.csv
Tom
Alice
Watson
3. コマンドラインから引数を与える
プログラム部分をf
オプションを使ってファイルで与えた場合
実行した時に変数の値を指定したい場合などがあると思います
その時はv
オプションを使って変数に直接代入する
$ awk -f hoge.awk -v '変数=値'
例
hoge.awk
は1列目の値を定数倍するためのスクリプト
{ print $1 * k }
定数k
をコマンドライン引数として与える
$ echo "1" | awk -f hoge.awk -v 'k=2'
2
4. 区切り文字を複数指定する
文字1,文字2,...., 文字nを入力区切り文字に設定したい時
awk -F '[文字1文字2...文字n]' 'program'
のようにFオプション
に区切り文字にしたい文字を[]
で囲った値を渡す.
例
空白とカンマの両方を区切り文字として扱う
$ printf "a,b c" | awk -F '[, ]' '{ print $1, $2, $3 }'
a b c
のように、カンマと空白のどちらでも区切りられる.
5. パターンマッチに変数を使用する
match
関数を使ってパターンマッチを行う。
awk -v '変数=値' 'match( $0, 変数 ) { なにかしらの処理 }'
例
以下のようなファイルhuga.txt
から、変数に格納した値にマッチする行を取得する
a b c
d e f
$ awk -v 'str=e f' 'match( $0, str ){ print $0 }' huga.txt
d e f
6. CSV形式で出力する
hoge.awk
を以下のようにする
BEGIN { OFS = "," }
{
for (i=1; i<=NF; i++) {
printf "\"%s\"", $i;
if( i < NF ) printf "%s",OFS
}
}
END { printf "\n" }
列番号を表す変数i
を1
からNF
までfor
文で回す。
for
文内部では,printf
関数でダブルクォーテーションを囲ってから列区切り文字OFS
を出力。
プログラムファイルにhoge.awk
を指定して実行
awk -f hoge.awk
例
文字列a b,c d
を空白区切りしてCSV形式で出力
$ echo "a b,c d" | awk -f hoge.awk
"a","b,c","d"
余談ですが、AWKはダブルクォーテーション内の改行を区別できないため、カラム内に改行コードがあるCSVは正確に読み込めないことに注意。
7. スクリプト内でファイルを開く
getline
を使う。 AWKの公式では無闇なgetline
の使用は推奨されておらず、組み込み変数の上書きによる想定外の動きをすることが多いため、使うとしてもこの書き方を強く推奨しておく。
BEGIN {
while ( (getline var < ファイル名) > 0 ) {
print var
}
}
例
ファイルabc.txt
の値を行毎に出力する
BEGIN {
while ( (getline var < "abc.txt") > 0 ) {
print var
}
}
$ echo "abc" > abc.txt
$ echo "" | awk -f hoge.awk
abc
8. 合計・平均・分散・標準偏差を求める
1列目に対して合計・平均・分散・標準偏差を求めたい場合はhoge.awk
に以下のように記述
{
sum += $1
square_sum += $1 * $1
}
END {
if ( NR == 0 ) exit
average = sum / NR
variance = square_sum / NR - average * average
std_dev = sqrt( variance )
print " 合計 :", sum
print " 平均 :", average
print " 分散 :", variance
print "標準偏差:", std_dev
}
プログラムファイルにhoge.awk
を指定して実行
awk -f hoge.awk
例
以下のような内容のfuga.txt
の合計・平均・分散・標準偏差を求める
50
60
70
70
100
$ awk -f hoge.awk fuga.txt
合計 : 350
平均 : 70
分散 : 280
標準偏差: 16.7332
9. 相関係数を求める
1列目と2列目の相関係数を求めたい場合はhoge.awk
に以下のように記述
{
sum_x += $1
sum_x2 += $1 * $1
sum_y += $2
sum_y2 += $2 * $2
sum_xy += $1 * $2
}
END {
if ( NR == 0 ) exit
ave_x = sum_x / NR
ave_y = sum_y / NR
covariance = sum_xy / NR - ave_x * ave_y
std_dev_x = sqrt( sum_x2 / NR - ave_x * ave_x )
std_dev_y = sqrt( sum_y2 / NR - ave_y * ave_y )
R = covariance / (std_dev_x * std_dev_y)
print "相関係数:", R
}
プログラムファイルにhoge.awk
を指定して実行
awk -f hoge.awk
例
以下のような内容のfuga.txt
の相関係数を求める
50 50
50 70
80 60
70 90
90 100
$ awk -f hoge.awk fuga.txt
相関係数: 0.633518
最後に
いかがでしたでしょうか?
今回は長すぎない記事を目指して書いたので初心者さん向けではない情報量になってしまいました。 AWKに興味がある方はぜひWeb上に大量の記事があるので検索してみてください。
参考になったページ
CONTACT
お問い合わせ・ご依頼はこちらから