記事検索
月別アーカイブ
アクセスカウンター

    タグ絞り込み検索
    2014年03月26日12:54awkのフィールド参照について

    awkは$1,$2とかで入力行のフィールドを参照できるが、$iのように変数はつかえないと思っていた。というのはshではできないから。

    % cat foo
    echo $1
    I=1
    echo ${$I}
    % sh foo xxx yyy
    xxx
    foo: ${$I}: Bad substitution
    %
    

    awkだとこんな感じ。

    % echo xxx yyy | awk '{ I=1; print $I }'
    xxx
    % 
    

    awkはCに似せているだけあって値のセマンティックスなのにたいして、shはマクロ展開が基本なのでいろいろ違って当然なのだが、いったいどういう文法になっているのかFreeBSDのawkのソースコード(/usr/src/contrib/one-true-awk)をのぞいてみた。

    構成はlex.cが字句解析でawkgram.yがYACCをつかった構文解析になっている。

    lex.cを '$' で検索すると目的の箇所はすぐに見つかって、awkgram.yとあわせてみると$は優先度の高い演算子(INDIRECT/IVAR)として扱われていて還元規則が INDIRECT term となっているため、何でもかけると思ってよいだろう。したがってふつうに $1, $2, $variable かけるのはまったくとうぜんなのであった。

    lex.cをみるとなぜか$NFは$(NF)として扱われているが、これは /* very special */ とコメントがかいてあるが、意味は理解できなかった。

    $func(xxx)とか$array[idx]も特別扱いされているようだ。

    % echo a b c | awk 'function f(x) { return x-1 }; { print $f(NF) }'
    b
    %
    

    関数引数も特別扱いされている。以下例でいうと関数fで引数xをつかって$xで参照しているところだ。awkには変数宣言がないので変数のスコープはグローバル変数か関数引数のどちらかしかないためこのような扱いが必要になっているようだ。

    % echo a b c | awk 'function f(x) { return $x }; { print f(NF-1) }'
    b
    %
    

    下のように書くとxはグローバル変数になるためだ。

    % echo a b c | awk 'function f() { return $x }; BEGIN{x=2}; { print f() }'
    b
    % echo a b c | awk 'function f(y) { x=y; return $x }; { print f(NF-1) }'  
    b
    %
    

    関連リンク:

    koie



    このエントリーをはてなブックマークに追加

    トラックバックURL

    コメントする

    名前
     
      絵文字