古い記事
ランダムジャンプ
新しい記事
awk はテキスト形式のデータの処理を得意とするプログラミング言語。sed と同じで、複雑なことは苦手だけど手軽で便利。

以下、ワンライナー利用を前提とした awk の必要最小限のメモ。

レシピ


指定フィールド(カラム)を表示:
awk '{print $1}'
awk '{print $3,$2}'

条件にあったら出す:
awk '$1 > 0 {print $2} $1 <= {print $1}'
awk '$1=="P" {print NR, $0}'
awk '{if($1<-1 || 5<$1) print}'
awk '{if($1>0 && $1<10)print"P";else print}'

正規表現:
awk '/RT/ {print NR,$0}'
awk '$2~/RT/ {printf("%06d %s\n", NR,$1)}'

正規表現でのマッチ箇所の取り出し・後方参照・文字列置換:
awk 'match($0, /(P|N)/) {print substr($0, RSTART, RLENGTH)}'
gawk {'print gensub(/^(.)\t/,"[\\1] ","g",$0)'}

空行を無視:
awk 'NF > 0 {print $1}'
awk '!/^$/ {print}'

区切り文字を指定:
awk -F'\t' '$2~/です/ {print sprintf("%06d %s", NR,$0)}'
awk -F, '{print NR,$3}'
awk -F' ' '{print $2}'
echo "A,1 B,2 C,3" | awk 'BEGIN{FS=",";RS=" ";OFS="\t"}{print$1,$2}'

数値の合計:
awk '{s+=$1}END{print s}'
awk 'BEGIN{print"NUM","SUM1","SUM2"}{s1+=$1;s2+=$2}END{print NR,s1,s2}'
awk 'BEGIN{OFMT="%.2f";print"NUM","VAL","CUM"}{s+=$1;print NR,$1,s}'

ラベルで集計:
echo "A 9\nB 2\nC 3\nA 5\nB 4" |\
awk '{s[$1]+=$2}END{for(k in s){print k" "s[k]}}'

標準偏差と偏差値:
echo "12\n67\n25\n37\n52\n40\n13\n29\n5\n93" |\
awk '{s+=$1;v[NR]=$1}END{a=s/NR;for(i in v){r+=(v[i]-a)^2};print sqrt(r/NR)}'

echo "12 67 25 37 52 40 13 29 5 93" |\
awk 'BEGIN{RS=" "}{s+=$1;v[NR]=$1}END{a=s/NR;
for(i in v){r+=(v[i]-a)**2};sd=sqrt(r/NR);
for(i=1;i<=NR;i++){print v[i],(v[i]-a)/sd*10+50}}'
(ref. 【Perl】標準偏差と偏差値の計算[2010-07-28-4])

辞書とマッチするカラムを置き換える:
cat a.dic
ABC 1
MNO 2
XYZ 3

cat a.txt
104 ABC this
780 MNO is
459 XYZ pen
482 ABC it

awk '!f{f=FILENAME}{if(f==FILENAME){d[$1]=$2}else
{if(d[$2]){print$1,d[$2],$3}else{print}}}' a.dic a.txt
104 1 this
780 2 is
459 3 pen
482 1 it
(ref. 【Perl】辞書とマッチするカラムを別なものに置換する【ワンライナー】[2015-09-01-4])

オプション・変数・関数


  • "-F" : 区切り文字を指定
  • $0 : 読み込んだ行の全体
  • NR : 行の数、行番号
  • NF : 列の数、フィールド数(カラム数)
  • FILENAME : 読み込んでるファイル名
  • RS : 入力の行区切り文字
  • FS : 入力の列区切り文字 ("-F"オプション)
  • ORS : 出力の行区切り文字
  • OFS : 出力の列区切り文字
  • OFMT : 数値の出力形式
  • BEGIN{}, END{} : 読み込み前と読み込み後に実行
  • cos, exp, getline, index, int, length, log, match, sin, split, sprintf, sqrt, substr
  • if, while, do, for, break, continue, print, printf, next, exit, delete

コメント


昔、「awk から多く学ぼう!」と言いながらいろいろやったけどそれほど多くは学べず、結局「大は小を兼ねる」で Perl を使ってる。Perl はテキスト・データ処理以外もできるし、柔軟性も汎用性も高い。

awk って、文字列置換まわりが sed 仕様だったら良かったんだけどねえ。って、それが Perl か。

参考


この記事に言及しているこのブログ内の記事