シングルパスでファイルのプレースホルダーを埋める
質問
プレースホルダー文字列を含むスケルトンテキストファイルがあります:
blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$
など。特定の「フォーム」プレースホルダーは重要ではありません。特定の実装に最も適したものに変更できます。
プレースホルダーの値を知っているbashスクリプトがあり、プレースホルダーを値に置き換えて新しいファイルを生成する必要があります。
#! /bin/sh
PLACEHOLDER_1 = 'string 1'
PLACEHOLDER_2 = 'multiline
string
2'
# TODO: Generate file output.txt from file output.template
# using placeholders above.
これはsedを使用して複数のパスで実行できますが、面白くありません。 Perlを使用したくないしない。 textutilsとbashのみを使用したい。
1回のパスで必要なことを行う最良の方法は何ですか?
解決
1回のパスでsedを使用して置換を実行できます。 1つのコマンドですべての置換を指定する必要があります。
eg。
sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>
他のヒント
sedを使用せずに実行する方法は次のとおりです。
最初に、プレースホルダーがbash変数であるわずかに変更されたテンプレートファイル:
blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2
そしてスクリプト:
#! /bin/sh
templatefile=output.template
outputfile=output.txt
PLACEHOLDER_1='string 1'
PLACEHOLDER_2='multiline
string
2'
# DONE: Generate file output.txt from file output.template
# using placeholders above.
echo "$(eval "echo \"$(cat $templatefile)\"")" > $outputfile
これは、スクリプト内に含まれているテンプレートをデモンストレーションするバージョンですが、ひねりが加えられています。また、テンプレートファイルバージョンでも使用できるデフォルト値に加えて、テンプレートで数学を実行できます。
#! /bin/sh
template='blah blah blah
blah $PLACEHOLDER_1
blah
${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some
lines
of
text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'
# default operands to zero (or 1) to prevent errors due to unset variables
outputfile=output.txt
# gears spin, bells ding, values for placeholders are computed
PLACEHOLDER_1='string 1'
PLACEHOLDER_2='multiline
string
2'
VAL_1=2
VAL_2=4
unset PLACEHOLDER_3 # so we can trigger one of the defaults
# Generate file output.txt from variable $template
# using placeholders above.
echo "$(eval "echo \"$template\"")" > $outputfile
sedなし、ループなし、毛むくじゃらのネストと引用符のみ。すべての引用がテンプレートファイル内の悪意のあるものからあなたを保護すると確信していますが、それを保証するつもりはありません。
前の答えに基づいて、おそらく配列を使用してsed文字列を計算しますか?
#!/bin/sh
PLACEHOLDER[0]='string 1'
PLACEHOLDER[1]='multiline
string
2'
s="sed -i "
for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do
echo ${PLACEHOLDER[$i]}
s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;"
done
echo $s
ただし、複数行の文字列では失敗するようです。
Bash配列の移植性がどの程度かはわかりません。上記のスニペットは&quot; GNU bash、バージョン3.2.17(1)-release(i386-apple-darwin9.0)&quot;
でテストされました私のbashのみのソリューション:
TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""
まったく同じものを探していたため、この質問につまずいたばかりで、 envsubst(1)
が見つかりました。
環境変数の使用を気にしない場合は、 envsubst を使用できます。
PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline
string
2' envsubst < output.template
変数がたくさんある場合は、それらをファイルに保存して source
するだけです(ソースファイルの最後で export
を使用することを忘れないでください!)