ファイルの先頭にテキストを追加するスクリプト

awk でパイプで入力されたものと引数で指定されたファイルと同時に記述した場合には、どちらを表示するでしょうか?

例えば以下のようなケースです。

$ cat test.txt
foo
bar
baz

$ echo "# this is sample file" | nawk '{print $0}' test.txt

実際には実行してみると分かると思いますが、パイプから入力されるものは無視されます。

$ echo "# this is sample file" | nawk '{print $0}' test.txt
foo
bar
baz

そうした中で、ファイルの先頭にテキストを追加するスクリプトのような仕様を満たすものはどうやって作れば良いでしょうか。 これには標準入力 (この場合パイプ) からの入力を getline で処理します。

#! /usr/bin/gawk -f
# append_header.awk

BEGIN {
    while (getline < "/dev/stdin" > 0) {
        print $0;
    }
    close("/dev/stdin");
}

{
    print $0;
}

実際に実行してみましょう。

$ echo "# this is sample file" | nawk -f append_header.awk test.txt
# this is sample file
foo
bar
baz

うまく動作しました。

ただし、awk の特性上、以下のようにすると標準入力待ちになってしまいます。

$ nawk -f append_header.awk test.txt
(ここで標準入力待ちになります。^D (CTRL + D) を押すと test.txt が表示されます)
foo
bar
baz

入力を間違えると標準入力待ちになることは awk ではしばしばあるので、注意したいところです。

追加 (2009-04-04)

getline持ち出さないでも、ファイル名のところに - を置けば済むような? と意見をいただいたのですが、すっかりファイル名に '-' (ハイフン) を指定したときの挙動を忘れていました。 ファイル名に '-' を指定すると標準入力になるため、簡単に記述することができます。

$ echo "# this is sample file" | nawk '{print $0}' - test.txt
# this is sample file
foo
bar
baz

もちろん、最後に付ける場合には以下のようにすれば、簡単に処理することができます。

$ echo "# this is sample file" | nawk '{print $0}' test.txt -
foo
bar
baz
# this is sample file

ご意見ありがとうございました。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png