6

プレースホルダー文字列を含むスケルトン テキスト ファイルがあります。

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 回のパスでやりたいことを実行する最善の方法は何ですか?

4

5 に答える 5

11

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 もループもありません。毛むくじゃらのネスティングと引用符だけです。すべての引用がテンプレート ファイル内の悪意のあるものから保護すると確信していますが、それを保証するつもりはありません。

于 2009-05-29T05:37:55.867 に答える
9

sed を使用して、1 回のパスで置換を行うことができます。1 つのコマンドですべての置換を指定するだけです。

例えば。

sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>
于 2009-01-02T16:22:14.610 に答える
5

前の回答に基づいて、おそらく配列を使用して 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 配列がどの程度移植可能かはわかりません。「GNU bash、バージョン 3.2.17(1)-release (i386-apple-darwin9.0)」でテストされた上記のスニペット

于 2009-01-02T17:28:15.600 に答える
2

私のbashのみの解決策:

TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""
于 2010-10-26T15:51:53.450 に答える
1

まったく同じものを探していたので、この質問に出くわしましenvsubst(1)た.

環境変数の使用を気にしない場合は、 envsubstを使用できます。

PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
string 
2' envsubst < output.template 

変数がたくさんある場合は、それらをファイルに保存することができます(ソース ファイルの最後でsource使用することを忘れないでください!)。export

于 2015-03-31T20:54:37.603 に答える