AWKのstatementsと組込関数

アクションの記述は式を並べることで行いますが、基本的に Cと同じ式が書 けます。また、次のような組み込みの数値関数が計算に使えます。表中のexpr は数を値とする式です。

atan2(y,x) y/x の逆正接(ラジアン単位)
cos(expr) 余弦(与える値はラジアン)
exp(expr) 指数関数
int(expr) 整数への変換
log(expr) 自然対数
rand() 0 から 1 の間の乱数
sin(expr) 正弦(与える値はラジアン)
sqrt(expr) 平方根
srand(expr) 式 expr の値を乱数生成関数の種として用いる。式 expr が与えられなかった場合は、時刻が用いられる。直前の種の値を返す。

さらに以下の文字列操作用の組込関数を持っています。

gsub(r,s,t) 文字列t中で正規表現rにマッチした部分をsに置換する。 置換した個数を返す。tを指定しなかった場合は$0が用いられる。
index(s,t) 文字列sに含まれる文字列tの位置を返す。tが含まれていない場合は0を返す。
length(s) 文字列sの長さを返す。sを指定しなかった場合には$0の長さを返す。
match(s,r) 文字列sで正規表現rにマッチする位置を返す。マッチしない場合は0を返す。 RSTARTとRLENGTHの値が設定される。
split(s,a,r) 文字列sを正規表現rを用いて分割し、配列aに格納する。 rが省略された場合はFSが用いられる。配列aの内容は、いったんクリアされる。
sprintf(fmt,list) フォーマットfmtに従ってlistを整形し、結果の文字列を返す。
sub(r,s,t) gsub()と同様。ただし、最初にマッチした文字列のみが置換される。
substr(s,i,n) 文字列sのi文字目からn文字の部分を返す。nが省略された場合、 i文字目以降の部分が返される。
tolower(str) 文字列strをコピーし、大文字をすべて小文字に変換したものを返す。 アルファベットではない文字は変化しない。
toupper(str) 文字列strをコピーし、小文字をすべて大文字に変換したものを返す。 アルファベットではない文字は変化しない。

例えばgsubは次のように使います。

    % gawk '{gsub(/新潮/, "しんちょう"); print; }' miyabe.csv 
    書名,本体価格,発行,発行社,文庫,備考
    火車,743,98/02/01,しんちょう社,しんちょう文庫 み-22-8,
    かまいたち,505,96/09/01,しんちょう社,しんちょう文庫 み-22-6,短編集
    蒲生邸事件,1650,96/10/10,毎日新聞社,
        (省略)

漢字の「新潮」が「しんちょう」に置き換わっています。これは単純な置き換 えにすぎませんが、正規表現を少し覚えるともっと複雑なことができます。

少々実用的な例を上げましょう。あるディレクトリの中のファイル名が全部大 文字のとき、それを小文字に変換したいとします。

    % ls
    AWK-INTRO.AUX  FS.0.AWK  MAKEFILE        SAMPLE1.DATA  SEC3.TEX
    AWK-INTRO.DVI  FS.AWK    MAKEFILE.FINAL  SEC0.TEX      SIN.AWK
    AWK-INTRO.LOG  GSUB.AWK  MIYABE.CSV      SEC1.TEX      SUM.AWK
    AWK-INTRO.TEX  KUKU.AWK  MIYABE.DATA     SEC2.TEX

さて、ひとつひとつ

    % mv AWK-INTRO.AUX awk-intro.aux

とやりますか? 私ならこうします[*]

    % ls | gawk '{print "mv -v", $0, tolower($0);}'
    mv -v AWK-INTRO.AUX awk-intro.aux
    mv -v AWK-INTRO.DVI awk-intro.dvi
    mv -v AWK-INTRO.LOG awk-intro.log
    mv -v AWK-INTRO.TEX awk-intro.tex
    mv -v FS.0.AWK fs.0.awk
        (省略)

この出力は、実行したいmvコマンドの羅列になっていますね。この出力をパイ プでshに渡してやれば、お望みの結果となります [*]

    % ls | gawk '{print "mv -v", $0, tolower($0);}' | sh
    AWK-INTRO.AUX -> awk-intro.aux
    AWK-INTRO.DVI -> awk-intro.dvi
    AWK-INTRO.LOG -> awk-intro.log
    AWK-INTRO.TEX -> awk-intro.tex
    FS.0.AWK -> fs.0.awk
        (省略)
    % ls
    awk-intro.aux  fs.0.awk  makefile        sample1.data  sec3.tex
    awk-intro.dvi  fs.awk    makefile.final  sec0.tex      sin.awk
    awk-intro.log  gsub.awk  miyabe.csv      sec1.tex      sum.awk
    awk-intro.tex  kuku.awk  miyabe.data     sec2.tex
    %

このように AWKを使って実行したいコマンドの列を全部作らせておいて、そ れをshに喰わせる(shの入力にする)のです。

このアイデアにsubなどの文字列操作関数などを組合わせると、沢山のファイ ルの名前の一部だけを小文字にするとか、ファイル名の一部に通し番号を振っ たりすることが簡単にできます。

なお、mvにオプション-vを付けたのは、この実行例のように変更の様子を表示 させたかっただけなので不用なら外してください。

OGURISU Osamu
2004-01-15