概要
AWKには、awkコマンドへ値やシェル変数を渡す機能が存在する。
一般的には、-vオプションを用いることが多い。
しかし、-vオプションの他にも、もう1つ別の方法が存在する。
本記事では、それら2つの方法の利用法と、それぞれの差異を述べる。
実行環境
- Arch Linux (x86_64, 4.2.5-1-ARCH)
- dash (0.5.8)
- gawk (4.1.3)
方法1
ファイル名引数として、値を渡す。
awkコマンドのスクリプトの直後に、awkで用いる変数varと代入する値value(もしくはシェル変数)を記述すれば良い。
$ awk 'script' var=value file
以下に具体例を示す。
$ cat file
man co
$ awk 'BEGIN{print num} END{print num}' num=100 file
100
方法2
-vオプションを用いて、値を渡す。
awkコマンドの-vオプションに続き、awkで用いる変数varと代入する値value(もしくはシェル変数)を記述すれば良い。
$ awk -v var=value 'script' file
以下に具体例を示す。
$ cat file
man co
$ echo | awk -v "sh=$SHELL" 'BEGIN{print sh} END{print sh}' file
/usr/bin/dash
/usr/bin/dash
各方法の差異
上記2つの方法の違いは、BEGINブロックにおける代入した値の扱いである。
方法1では、BEGINブロック内では代入した値を参照できない。
しかし、方法2では、BEGINブロック内でも代入した値を参照することができる。
以下に差異を示す。
$ hoge="hoge hage hige"
$ echo | awk 'BEGIN{print var} {print var} END{print var}' "var=$hoge"
hoge hage hige
hoge hage hige
$ echo | awk -v "var=$hoge" 'BEGIN{print var} {print var} END{print var}'
hoge hage hige
hoge hage hige
hoge hage hige
複数の値を渡す場合
複数の値をawkコマンドへ渡したい場合、awk変数への代入を続けて記述すれば良い。
方法1、方法2のどちらの場合でも、代入を複数回おこなえば良い。
以下に具体例を示す。
$ echo | awk '{print foo, bar}' foo="a" bar="b"
a b
$ echo | awk -v "foo=$HOME" -v "bar=$CPUTYPE" '{print foo, bar}'
/home/gin x86_64
参考にしたもの
- $ man awk
- The GNU Awk User's Guide - awkを実行する 〈http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_15.html#SEC136〉
- 『sed & awkプログラミング 改訂版』、Dale Dougherty, Arnold Robbins 共著、福崎 俊博 訳、オライリー・ジャパン
- ShellScript - awkからシェル変数を参照する - Qiita 〈http://qiita.com/tkyk@github/items/1622970830262355a5a3〉
雑記
-
このawkへ値を渡す2種類の方法は、AWKの仕様として定められているらしい。
- なので、gawk以外の処理系、nawk・mawkでも同じ動作をする。
-
どうして2種類の方法が存在するのか、分からない。
- この理由に関しては、参考にしたもの2.に記述があった。引用してみる。
初期のawk処理系の一部では、変数代入がすべてのファイル名の 前にあったときに、その代入をBEGINルールが実行される前に 行っていた。awkの振る舞いはこのために一貫性を欠いていた。 つまり、一部のコマンドライン上の代入はBEGINルール の内側にあるかのように扱われたが、そうでないものもあった。 しかし、一部のアプリケーションはこの"仕様"に依存していた。 awkがより一貫性を持つように変更されたとき、 `-v'オプションがこのような古い動作を前提としていた アプリケーションに適応させるために追加された。
- ただ、-vオプションを使わない方法は、どのような場面で活用するんだろう... 思いつかない。