複数のファイルにスペースを含むヘッダー行を追加したいです。
これが私が今まで持っているものです:
#!/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
ファイルの内容を出力するだけですcat
。printf
出力を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
):BEGINFILE
awk
#!/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) }' "$@"