awkコマンドへ値を渡す手法のまとめ


概要

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

参考にしたもの

  1. $ man awk
  2. The GNU Awk User's Guide - awkを実行する 〈http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_15.html#SEC136
  3. 『sed & awkプログラミング 改訂版』、Dale Dougherty, Arnold Robbins 共著、福崎 俊博 訳、オライリー・ジャパン
  4. 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オプションを使わない方法は、どのような場面で活用するんだろう... 思いつかない。