awkを使用して複数のファイルにヘッダーを追加する方法

awkを使用して複数のファイルにヘッダーを追加する方法

複数のファイルにスペースを含むヘッダー行を追加したいです。

これが私が今まで持っているものです:

#!/bin/bash
# script name is "add_header.sh"
# ARG1 = HEADER STRING
# ARG2,3,... = ARRAY OF FILES TO ADD HEADER TO, RELATIVE DIRECTORY

HEADER=$1 
shift 

for FILE in $@; do
    awk -v HEADER=$HEADER FILE=$FILE 'BEGIN{print HEADER} {print}' FILE > FILE.new
done

残念ながら、私のユースケースで実行すると、空白が原因で失敗します。

touch file1 file2 file3
./add_header.sh "some header with spaces" file1 file2 file3

これにより、次のエラーが発生します。

awk: fatal: cannot open file `with' for reading (No such file or directory)
awk: fatal: cannot open file `with' for reading (No such file or directory)
awk: fatal: cannot open file `with' for reading (No such file or directory)

Bash変数でスペースをエスケープする方法はありますか?各スペースの前に \ を使用してみましたが、エラーは次のように変更されます。

./add_header.sh "some\ header\ with\ spaces" file1 file2 file3
awk: fatal: cannot open file `with\' for reading (No such file or directory)
awk: fatal: cannot open file `with\' for reading (No such file or directory)
awk: fatal: cannot open file `with\' for reading (No such file or directory)

これはスペースがエスケープされないことを意味します。

ベストアンサー1

#!/bin/sh

header=$1; shift

for pathname do
    { printf '%s\n' "$header"; cat -- "$pathname"; } >"$pathname.new"
done

awkヘッダーと古いファイルの内容を関連付けたいので、ここでは実際には必要ありません。単純にヘッダ文字列を出力してから、printfファイルの内容を出力するだけですcatprintf出力をcat新しいファイルにリダイレクトします。

することができます本物を使用してこれを行うには、awk上記のコードのようにファイルを繰り返すか、awk明示的なシェルループなしで各ファイルを処理することができます。

明示的なシェルループを持つ最初のバリエーション:

#!/bin/sh

header=$1; shift

for pathname do
    header=$header awk 'BEGIN { print ENVIRON["header"] }; 1' "$pathname" >"$pathname.new"
done

awk上記の解決策はファイルごとに一度呼び出されるので、この回答のすべてのバリエーションの中で最も遅いです。

シェルのないループの2番目の変形(GNUのように理解する必要がありますawk):BEGINFILEawk

#!/bin/sh

header=$1; shift

header=$header awk '
    BEGINFILE { fname = FILENAME ".new"; print ENVIRON["header"] >(fname) }
    { print >(fname) }' "$@"

3番目の変形(最後のコード断片の移植可能な変形):

#!/bin/sh

header=$1; shift

header=$header awk '
    FNR == 1 { fname = FILENAME ".new"; print ENVIRON["header"] >(fname) }
    { print >(fname) }' "$@"

おすすめ記事