awk のスクリプトの基本構成
BEGIN{ データを読み込む前に行う処理 } pattern { データを読み込みながら行う処理 } END{ データ読み込み完了後に行う処理 }
awk のスクリプトの基本構成は上に示すとおり. patternを記載すると,その条件に合致する行の処理を行う.pattern を省略すると全行の処理を行う.
もし,データ読み込みを行わないで処理を行うなら,以下のように BEGIN で囲まれた部分のみを記述する.
BEGIN{ データを読み込む前に行う処理 }
基本
gawk -f awk_script.awk inp_data.txt > out_data.txt
この事例では,ファイルの設定は以下のとおり.
awk_script.awk | awk スクリプト(awk のプログラム) |
inp_data.txt | awk で処理する入力ファイル名 |
out_data.txt | awk で処理された結果を出力するファイル名 |
ARGC, ARGV の使用事例
事例(1)
実行用コマンド
gawk -f awk_ARGV_test.awk test1.txt para1 para2 para3 > out_ARGV.txt
awk スクリプト (awk_ARGV_test.awk)
BEGIN{ printf "ARGC=%d\n",ARGC for(i=0;i<=ARGC-1;i++){ printf "ARGV[%d]:%s\n",i,ARGV[i] } }
出力結果
ARGV[0] にはプログラム名の gawk があてられ,-f でオプション指定されたスクリプト名をとばして test1.txt 以降が ARGV[1] から ARGV[4] にあてられる.この事例では引数の数を示す ARGC は 5 となる.
ARGC=5 ARGV[0]:gawk ARGV[1]:test1.txt ARGV[2]:para1 ARGV[3]:para2 ARGV[4]:para3
事例(2)
実行用コマンド
gawk -f awk_result_2dim.awk out_2dim0_002.csv 2 33 44 59 > result_2dim0.csv
awk スクリプト (awk_result_2dim.awk)
BEGIN{ nd =ARGV[2] nu =ARGV[3] ns1=ARGV[4] ns2=ARGV[5] for(i=2;i<=5;i++){delete ARGV[i]} FS="," sigs=0;sigr=0 n=nd*2*4 } NR==nu{u=$5} ns1==NR,NR==ns2{sigs=sigs+$6;sigr=sigr+$7} END{printf "%d,%g,%g,%g\n",nd,u,sigs/n,sigr/n}
説明
上の awk スクリプトは,FEMの解析結果の打ち出し ( csv ファイル) の一部を読み取るものです. ここでの注意事項として,実行用バッチファイルの中で,スクリプト名の後ろに処理に必要となるパラメータを入力しています. ARGV[0] には「gawk」,ARGV[1] には入力ファイル名が格納され,ARGV[2] から ARGV[5] には数値を入力している「つもり」なのですが,「BEGIN」の中で必要な数値を変数に格納したら,ファイル名 ( ARGV[1] ) 以外の ARGV[] の配列要素を削除しています. これは,gawk は ARG[2] 以降もファイル名として読み込もうとしてエラーになってしまうため,これを避ける処置です. ちなみに「BEGIN」の中で ARGV[1] を削除すると,入力ファイル名が不定になり,うまく動きません.
データ読み込み処理部では,以下の処理を行っています.
- NR==nu が真となる行について,値 u をセットする.
- ns1==NR が真になる行から NR==ns2 が真になる行まで,sigs と sigr の総和をとる.
FILENAME, NR, FNR, NF の使用事例
入力サンプルデータ
|
|
|
実行用コマンド
gawk -f awk_NR_test.awk test1.txt test2.txt test5.txt > out_NR.txt
awk スクリプト (awk_NR_test.awk)
BEGIN{print "FILENAME NR FNR NF $1 $2 $3 $4 $5"} { switch(FILENAME){ case "test1.txt":printf "%s %3d %5d %5d %6.1f\n",FILENAME,NR,FNR,NF,$1;break case "test2.txt":printf "%s %3d %5d %5d %6d %6d\n",FILENAME,NR,FNR,NF,$1,$2;break case "test5.txt":printf "%s %3d %5d %5d %6d %6d %6d %6d %6d\n",FILENAME,NR,FNR,NF,$1,$2,$3,$4,$5;break } }
上のスクリプトでは,switchを使用し場合わけしているが,下のスクリプトでも同じ処理ができる.
BEGIN{print "FILENAME NR FNR NF $1 $2 $3 $4 $5"} FILENAME=="test1.txt"{printf "%s %3d %5d %5d %6.1f\n",FILENAME,NR,FNR,NF,$1} FILENAME=="test2.txt"{printf "%s %3d %5d %5d %6d %6d\n",FILENAME,NR,FNR,NF,$1,$2} FILENAME=="test5.txt"{printf "%s %3d %5d %5d %6d %6d %6d %6d %6d\n",FILENAME,NR,FNR,NF,$1,$2,$3,$4,$5}
出力結果
NR は,読み込んでいるファイルの変更によらず,スクリプトの最初から最後までの読み込んでいる現在行を示す. FNR はファイルごとに読み込んでいる現在行を示す.NF は列数を示す.
FILENAME NR FNR NF $1 $2 $3 $4 $5 test1.txt 1 1 1 0.1 test1.txt 2 2 1 0.2 test1.txt 3 3 1 0.3 test1.txt 4 4 1 0.4 test1.txt 5 5 1 0.5 test2.txt 6 1 2 1 10 test2.txt 7 2 2 2 20 test2.txt 8 3 2 3 30 test2.txt 9 4 2 4 40 test2.txt 10 5 2 5 50 test5.txt 11 1 5 1 10 100 1000 10000 test5.txt 12 2 5 2 20 200 2000 20000 test5.txt 13 3 5 3 30 300 3000 30000 test5.txt 14 4 5 4 40 400 4000 40000 test5.txt 15 5 5 5 50 500 5000 50000
関数の使用事例
スクリプトawk_test.awkを読み込んでout_test.txtに出力する.入力ファイルはないケース.
実行用コマンド
gawk -f awk_test.awk > out_test.txt
関数使用事例のスクリプト (awk_test.awk)
BEGIN{ pi=3.141592654 x= 3.9 ;printf "int(x) : x=%+8.3f int(x)=%+d\n",x,int(x) x=-3.9 ;printf "int(x) : x=%+8.3f int(x)=%+d\n",x,int(x) x= 4.0 ;printf "sqrt(x) : x=%+8.5f sqrt(x)=%+8.5f\n",x,sqrt(x) x= 1.0 ;printf "exp(x) : x=%+8.5f exp(x)=%+8.5f\n",x,exp(x) x=exp(1) ;printf "log(x) : x=%+8.5f log(x)=%+8.5f\n",x,log(x) x=pi ;printf "sin(x) : x=%+8.5f sin(x)=%+8.5f\n",x,sin(x) x=pi ;printf "cos(x) : x=%+8.5f cos(x)=%+8.5f\n",x,cos(x) y=1;x=1.7;printf "atan2(y,x): y=%+3.1f x=%+3.1f atan2(y,x)=%+8.5f(%4.1fdeg)\n",y,x,atan2(y, x),atan2(y, x)/pi*180 y=1;x=1.0;printf "atan2(y,x): y=%+3.1f x=%+3.1f atan2(y,x)=%+8.5f(%4.1fdeg)\n",y,x,atan2(y, x),atan2(y, x)/pi*180 printf "rand() : rand()=%g\n",rand() printf "rand() : rand()=%g\n",rand() srand(5); printf "srand(x) : srand(5) rand()=%g\n",rand() srand(5); printf "srand(x) : srand(5) rand()=%g\n",rand() print s1="wantaro";s2="taro" ;printf "index(s1,s2) : s1=\"%s\" s2=\"%s\" index(s1,s2)=%d\n",s1,s2,index(s1,s2) s1="wantaro";s2="xyza" ;printf "index(s1,s2) : s1=\"%s\" s2=\"%s\" index(s1,s2)=%d\n",s1,s2,index(s1,s2) st="wantaro" ;printf "length(st) : st=\"%s\" length(st)=%d\n",st,length(st) st="wantaro" ;printf "match(st,/*/) : st=\"%s\" match(st,/taro/)=%d\n",st,match(st,/taro/) st="wantaro" ;printf "match(st,/*/) : st=\"%s\" match(st,/xyza/)=%d\n",st,match(st,/xyza/) st="wan-ta-ro" ;printf "split(st,a,\"*\"): st=\"%s\" split(st,a,\"-\")=%d a[1]=\"%s\" a[2]=\"%s\" a[3]=\"%s\"\n",st,split(st,a,"-"),a[1],a[2],a[3] st=sprintf("pi is %.5f",pi);printf "sprintf(\"*\",x) : pi=%.5f st=sprintf(\"pi is %%.5f\",pi) st=\"%s\"\n",pi,st s1="wanwantaro";s2="Kon-" ;printf "sub(/*/,s2,s1) : s1=\"%s\" s2=\"%s\" sub(/wan/,s2,s1)=%d s1=\"%s\"\n",s1,s2,sub(/wan/,s2,s1),s1 s1="wanwantaro";s2="Kon-" ;printf "gsub(/*/,s2,s1): s1=\"%s\" s2=\"%s\" gsub(/wan/,s2,s1)=%d s1=\"%s\"\n",s1,s2,gsub(/wan/,s2,s1),s1 st="wantaro";i=4;n=2 ;printf "substr(st,i,n) : st=\"%s\" i=%d n=%d substr(st,i,n)=\"%s\"\n",st,i,n,substr(st,i,n) st="WANTARO" ;printf "tolower(st) : st=\"%s\" tolower(st)=\"%s\"\n",st,tolower(st) st="wantaro" ;printf "toupper(st) : st=\"%s\" toupper(st)=\"%s\"\n",st,toupper(st) print printf "%s\n","Note) * is something of character or strings." }
関数使用事例の出力事例
int(x) : x= +3.900 int(x)=+3 int(x) : x= -3.900 int(x)=-3 sqrt(x) : x=+4.00000 sqrt(x)=+2.00000 exp(x) : x=+1.00000 exp(x)=+2.71828 log(x) : x=+2.71828 log(x)=+1.00000 sin(x) : x=+3.14159 sin(x)=-0.00000 cos(x) : x=+3.14159 cos(x)=-1.00000 atan2(y,x): y=+1.0 x=+1.7 atan2(y,x)=+0.53172(30.5deg) atan2(y,x): y=+1.0 x=+1.0 atan2(y,x)=+0.78540(45.0deg) rand() : rand()=0.237788 rand() : rand()=0.291066 srand(x) : srand(5) rand()=0.664045 srand(x) : srand(5) rand()=0.664045 index(s1,s2) : s1="wantaro" s2="taro" index(s1,s2)=4 index(s1,s2) : s1="wantaro" s2="xyza" index(s1,s2)=0 length(st) : st="wantaro" length(st)=7 match(st,/*/) : st="wantaro" match(st,/taro/)=4 match(st,/*/) : st="wantaro" match(st,/xyza/)=0 split(st,a,"*"): st="wan-ta-ro" split(st,a,"-")=3 a[1]="wan" a[2]="ta" a[3]="ro" sprintf("*",x) : pi=3.14159 st=sprintf("pi is %.5f",pi) st="pi is 3.14159" sub(/*/,s2,s1) : s1="wanwantaro" s2="Kon-" sub(/wan/,s2,s1)=1 s1="Kon-wantaro" gsub(/*/,s2,s1): s1="wanwantaro" s2="Kon-" gsub(/wan/,s2,s1)=2 s1="Kon-Kon-taro" substr(st,i,n) : st="wantaro" i=4 n=2 substr(st,i,n)="ta" tolower(st) : st="WANTARO" tolower(st)="wantaro" toupper(st) : st="wantaro" toupper(st)="WANTARO" Note) * is something of character or strings.
asort 関数の使用事例
- asort により文字列の昇順ソートを行う.
- asort(a,b) とすると,a に元の文字列,b に並び替えられた文字列が格納される.
- asort(a)とすると a に並び替えられた文字列が格納される.
- 大文字と小文字が混在する場合,大文字が優先されて並び替えられる.
- 大文字と小文字の区別をなくしたい場合は,tolower() で小文字に置き換えてソートする.
awk スクリプト | 実行結果 |
BEGIN{ a[1]="snow" a[2]="snow1" a[3]="snow2" a[4]="RosyBrown1" a[5]="RosyBrown2" a[6]="snow3" a[7]="LightCoral" a[8]="IndianRed1" a[9]="RosyBrown3" a[10]="IndianRed2" a[11]="RosyBrown" n=asort(a,b) printf "%12s %12s\n","a[i]","b[i]" for(i=1;i<=n;i++){ printf "%12s %12s\n",a[i],b[i] } for(i=1;i<=n;i++){ a[i]=tolower(a[i]) } print n=asort(a) printf "%12s\n","a[i]" for(i=1;i<=n;i++){ printf "%12s\n",a[i] } } |
a[i] b[i] snow IndianRed1 snow1 IndianRed2 snow2 LightCoral RosyBrown1 RosyBrown RosyBrown2 RosyBrown1 snow3 RosyBrown2 LightCoral RosyBrown3 IndianRed1 snow RosyBrown3 snow1 IndianRed2 snow2 RosyBrown snow3 a[i] indianred1 indianred2 lightcoral rosybrown rosybrown1 rosybrown2 rosybrown3 snow snow1 snow2 snow3 |
ファイルに処理結果を出力
事例 (1)
gawk "BEGIN{pi=3.141592654;for(i=-89;i<=270;i++){print 0.3*cos(i/180*pi)-7.0,1.5*sin(i/180*pi)+52.4}}" > _temp.txt
この事例では,中心(-7.0,52.4),短半径 0.3,長半径 1.5 の楕円の座標をファイル _temp.txt に出力している. データ区切りはブランク.
事例 (2)
gawk "{if(NR==1){sub(/#/,\"\",$0);printf \"0.3 14.5 12 0 0 ML %%s\n\",$0}}" %inp_1% > _val.txt
- 変数 inp_1 にセットされた入力ファイルの行数が 1 だったら,「0.3 14.5 12 0 0 ML %%s」という文字列を出力ファイル _val.txt に書き出す.
- %sには,sub 関数により処理された入力ファイル1行目の全文字列$0が当てはめられる.
- sub(/#/,\"\",$0)は,文字列$0の中の「#」という文字を削除する処理を行う.
事例 (3)
gawk "{if(0<index($0,\""<"h2">"\")) print $0}" org_f90.html > test1_f90.txt
- HTML ファイルの見出しを検索してファイルに書き出す.
- 不等号はコマンドプロンプトのリダイレクト記号なので, "<" や ">" のように double-quotation で囲む.
- double-quotation 自体の出力には,前に\マークを加える.(\")
- double-quotation だらけで見づらいので注意が必要!
ソートされたフォント名一覧を作成する
dir c:\windows\Fonts\*.ttf > fname.txt dir c:\windows\Fonts\*.ttc >> fname.txt gawk "{if(index($1,\"/\")==5)print $4}" fname.txt > fname1.txt gawk "{print tolower($0),$0}" fname1.txt > fname2.txt gawk "{str[NR]=$0}END{n=asort(str);for(i=1;i<=n;i++)print str[i]}" fname2.txt > fname3.txt gawk "{print $2}" fname3.txt > inp_fname.txt
GMT の psxy にデータを渡す
事例 (1)
gawk "BEGIN{FS=\",\"}{if(568<=NR&&NR<=610)print $2,$5*1000}" %inp_4% | psxy -R -J -B -W5 -P -O -K >> %fig_out%
この事例では,変数 inp_4 にセットされているファイルから gawk でデータを読み取り,処理結果を GMT の psxy に渡している. awk での処理内容は,以下のとおり.
- 入力データファイルのデータ区切り文字を comma「,」にセット.
- 入力ファイルの行数 568 から 610 までの数値並びのうち,第 2 列を x 値,第 5 列を1000倍したものを y 値として psxy に渡す.
事例 (2)
gawk "BEGIN{FS=\",\"}{if(3<=NR)print NR-2.5,$7}" dat_inp_climate.csv | psxy -R -J -Sb1u -W1 -G0/255/255 -B -K -O >> %fig_out%
- 入力データファイルのデータ区切り文字を comma「,」にセット.
- 入力ファイルの行数が 3以上になったら,x 値を入力ファイルの行数マイナス 2.5 (NR-2.5) 第 7 列を y 値として psxy に渡す.
GMT の pstext にデータを渡す
gawk "{if(NR==35) printf \"9.5 5.5 12 0 0 MR %%gm@+3@+/s\",$2}" _temp0.txt | pstext -R -J -Gred -P -O -K >> %fig_out%
- 入力ファイルの行数が 35 になったら,「9.5 5.5 12 0 0 MR %%gm@+3@+/s」という文字列を pstext に渡す.
- %gには,入力ファイルの2列目の数値が当てはめられる.