[更新情報]

▽Go to footer

目次

awk のスクリプトの基本構成

BEGIN{ データを読み込む前に行う処理 }
pattern { データを読み込みながら行う処理 }
END{ データ読み込み完了後に行う処理 }

awk のスクリプトの基本構成は上に示すとおり. patternを記載すると,その条件に合致する行の処理を行う.pattern を省略すると全行の処理を行う.

もし,データ読み込みを行わないで処理を行うなら,以下のように BEGIN で囲まれた部分のみを記述する.

BEGIN{ データを読み込む前に行う処理 }



スクリプトファイルを読み込んで gawk を実行

基本

gawk -f awk_script.awk inp_data.txt > out_data.txt

この事例では,ファイルの設定は以下のとおり.

awk_script.awkawk スクリプト(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] を削除すると,入力ファイル名が不定になり,うまく動きません.

データ読み込み処理部では,以下の処理を行っています.




FILENAME, NR, FNR, NF の使用事例

入力サンプルデータ

test1.txt
0.1
0.2
0.3
0.4
0.5
test2.txt
1 10
2 20
3 30
4 40
5 50
test5.txt
1 10 100 1000 10000
2 20 200 2000 20000
3 30 300 3000 30000
4 40 400 4000 40000
5 50 500 5000 50000

実行用コマンド

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.



batch ファイルの中に awk スクリプトを直接書き込み gawk を実行

ファイルに処理結果を出力(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

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 での処理内容は,以下のとおり.

GMT の 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%

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%



凡例を作図するバッチファイルを作るawkスクリプトの解説

行番号を挿入するawkスクリプト

gawk "{printf \"%%03d  %%s\n\",NR,$0}" test.txt > test1.txt

凡例を作図するバッチファイルを作るawkスクリプト

001  # ****************************************
002  # Making batch file for legend drawing
003  # ****************************************
004  # Data format
005  # xlen  ylen  strP  dx  dy
006  # ipt  scl  llen
007  # strTX[NR]  strLW[NR]  strSS[NR]  strSG[NR]  strSW[NR]
008  # .........  .........  .........  .........  .........
009  # .........  .........  .........  .........  .........
010  # xlen, ylen : width and height of graph
011  # strP       : position of legend box in the graph
012  #              "bl" bottom left
013  #              "br" bottom right
014  #              "tr" top right
015  #              "tl" top left
016  # dx, dy     : minimum distance from axis to legend box
017  # ipt        : font size in point
018  # scl        : width/height of 1 font
019  # llen       : length of line
020  # strTX[]    : text
021  # strLW[]    : element of line (width, color, type)
022  # strSS[]    : type of symbol (type and dimension)
023  # strSG[]    : fill color of symbol (color)
024  # strSW[]    : external line of symbol (thickness and color)
025  #
026  # sx, sy     : width and height of legend box
027  # xx, yy     : bottom left of the legend box
028  #
029  BEGIN{
030      FS="$";
031  }
032  {
033      #*******************************
034      # Treatment of input file data
035      #*******************************
036      # gsub(/^ +/, "", $i);gsub(/ +$/, "", $i);
037      # erase of blanks at top and end of the strings
038      #
039      if(NR==1){
040          for(i=1;i<=5;i++){gsub(/^ +/, "", $i);gsub(/ +$/, "", $i);}
041          xlen=$1;ylen=$2;strP=$3;dx=$4;dy=$5;
042      }
043      if(NR==2){
044          for(i=1;i<=3;i++){gsub(/^ +/, "", $i);gsub(/ +$/, "", $i);}
045          ipt=$1;scl=$2;llen=$3;
046      }
047      if(3<=NR){
048          for(i=1;i<=5;i++){gsub(/^ +/, "", $i);gsub(/ +$/, "", $i);}
049          strTX[NR-2]=$1;strLW[NR-2]=$2;strSS[NR-2]=$3;strSG[NR-2]=$4;strSW[NR-2]=$5;
050      }
051  }
052  END{
053      #*******************************
054      # Calculation and output
055      #*******************************
056      nd=NR-2;
057      lmax=0;
058      for(i=1;i<=nd;i++){
059          ss=strTX[i]
060          gsub(/(@%%)[0-9]+(%%)/,"",ss);gsub(/(@%%%%)/,"",ss);gsub(/\\[0-9]+/,"\\",ss);gsub(/(@\+)/,"",ss);gsub(/(@\-)/,"",ss);gsub(/(@\#)/,"",ss);
061          if(lmax<length(ss))lmax=length(ss);
062      }
063      #=====================================
064      # making file for legend box
065      #=====================================
066      printf "echo %d %d  >_legend0.txt\n",0,0;
067      printf "echo %d %d >>_legend0.txt\n",1+lmax+1+llen+1,0;
068      printf "echo %d %d >>_legend0.txt\n",1+lmax+1+llen+1,nd;
069      printf "echo %d %d >>_legend0.txt\n",0,nd;
070      #=====================================
071      # making file for line length
072      #=====================================
073      for(i=1;i<=nd;i++){
074          printf "echo %d %.1f  >_legend%d.txt\n",1+lmax+1,nd-i+0.5,i;
075          printf "echo %d %.1f >>_legend%d.txt\n",1+lmax+1+llen,nd-i+0.5,i;
076      }
077      #=====================================
078      # difining dimension of legend box
079      #=====================================
080      sx=(ipt*(1+lmax+1+llen+1))*0.0353*scl;
081      sy=((2+ipt+2)*nd)*0.0353;
082      if(match(strP,"bl")!=0){xx=dx;yy=dy;}
083      if(match(strP,"br")!=0){xx=xlen-sx-dx;yy=dy;}
084      if(match(strP,"tr")!=0){xx=xlen-sx-dx;yy=ylen-sy-dy;}
085      if(match(strP,"tl")!=0){xx=dx;yy=ylen-sy-dy;}
086      #=====================================
087      # output of legend box
088      #=====================================
089      printf "psbasemap -R0/%d/0/%d -JX%.1f/%.1f -G255 -P -X%.1f -Y%.1f -O -K>>%s\n",1+lmax+1+llen+1,nd,sx,sy,xx,yy,"%fig_out%";
090      printf "psxy _legend0.txt -R -J -G255/255/255 -W3 -P -O -K>>%s\n","%fig_out%";
091      #=====================================
092      # output of line elements
093      #=====================================
094      for(i=1;i<=nd;i++){
095          if(match(strLW[i],"---")==0)printf "psxy _legend%d.txt -R -J -W%s -P -O -K>>%s\n",i,strLW[i],"%fig_out%";
096      }
097      #=====================================
098      # output of symbol
099      #=====================================
100      for(i=1;i<=nd;i++){
101          if(match(strSS[i],"---")==0){
102              if(match(strSG[i],"---")!=0&&match(strSW[i],"---")!=0){
103                  printf "echo %.f %.1f | psxy -R -J -S%s -P -O -K>>%s\n",1+lmax+1+0.5*llen,nd-i+0.5,strSS[i],"%fig_out%";
104              }
105              if(match(strSG[i],"---")==0&&match(strSW[i],"---")!=0){
106                  printf "echo %.f %.1f | psxy -R -J -S%s -G%s -P -O -K>>%s\n",1+lmax+1+0.5*llen,nd-i+0.5,strSS[i],strSG[i],"%fig_out%";
107              }
108              if(match(strSG[i],"---")==0&&match(strSW[i],"---")==0){
109                  printf "echo %.f %.1f | psxy -R -J -S%s -G%s -W%s -P -O -K>>%s\n",1+lmax+1+0.5*llen,nd-i+0.5,strSS[i],strSG[i],strSW[i],"%fig_out%";
110              }
111          }
112      }
113      #=====================================
114      # output of text
115      #=====================================
116      for(i=1;i<=nd;i++){
117          if(i==nd){
118              printf "echo 1 %.1f %d 0 0 ML %s | pstext -R -J -P -O >> %s\n",nd-i+0.5,ipt,strTX[i],"%fig_out%";
119          }else{
120              printf "echo 1 %.1f %d 0 0 ML %s | pstext -R -J -P -O -K>> %s\n",nd-i+0.5,ipt,strTX[i],"%fig_out%";
121          }
122      }
123  }
029-031
入力データファイルの区切り文字を「$」に指定
039-042
入力ファイル1行目の処理.
1列目から5列目までの文字に対し,gsub関数を使って最初と最後の空白を削除し,変数に格納.
043-046
入力ファイル2行目の処理.
1列目から3列目までの文字に対し,gsub関数を使って最初と最後の空白を削除し,変数に格納.
047-050
入力ファイル3行目以降の処理.
1列目から5列目までの文字に対し,gsub関数を使って最初と最後の空白を削除し,配列に格納.
056
凡例に描画する個数(データ処理の繰り返し数)を確定.
057-062
文字列長さの最大値の検索.
066-069
凡例を描く箱の大きさをファイル出力.
073-076
凡例に描画する線の長さをファイル出力.
080-085
凡例を描画する座標を特定.
089-090
凡例を描く箱を描画.
094-096
凡例の線を描画.
100-112
凡例の記号を描画.
116-122
凡例のテキストを描画.

使っている組み込み変数,組み込み関数

以下の説明は,「志村拓・鷲北賢・西村克信著,AWKを256倍使うための本,2008年10月6日,株式会社アスキー・メディアワークス発行」より抜粋したものです.

FS入力フィールドセパレータ.デフォルトはブランク
NR入力ファイルから読み込んで今までに処理した行の総数
gsub(正規表現,置換文字列,対象文字列)対象文字列中で正規表現に一致する文字列を全て置換文字列で置換する.戻り値は置換された数.対象文字列に変更を加えることに注意
length(対象文字列)対象文字列の長さをバイト数で返す
match(対象文字列,正規表現)対象文字列中で正規表現に一致する位置をバイト単位で返す.一致するものがなければ0を返す

正規表現

以下の説明は,「志村拓・鷲北賢・西村克信著,AWKを256倍使うための本,2008年10月6日,株式会社アスキー・メディアワークス発行」より抜粋したものです.判りやすいです.

. 任意の 1 文字に一致
* 前の文字の 0 個以上の繰り返しに一致
+ 前の文字の 1 個以上の繰り返しに一致
? 前に文字があるか、1 個あるかに一致
^ 行頭に一致
$ 行末に一致
(re) ( )で囲まれた正規表現 re をグループ化
[  ][   ]で囲まれた文字列の中の任意の 1 文字に一致
[^   ][^    で囲まれた文字列以外の文字に一致
re1|re2正規表現re1またはre2に一致する



inserted by FC2 system