複数行の文字列と文字列補間を処理する方法は?

複数行の文字列と文字列補間を処理する方法は?

どこかに複数行の文字列用のテンプレートを持ちたいとしましょう。

I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}

プレースホルダをユーザー入力に置き換える最善の方法は何ですか?ここにある文書は役に立ちますか?

答え1

\<newline> または文字 , , または が[a]複数行文字列に使用されていないか、正しく引用されていると仮定すると、このドキュメント(および変数)が最良の選択です。\$`

#!/bin/sh

placeholders="value one"
different="value two"
here="value three"
there="value four"

cat <<-_EOT_
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}.
_EOT_

実行される場合:

$ sh ./script
I have some
text with value one
in this and some value two
ones value three and value four.

もちろん、qoutingを正しく使用すると、変数も機能します。

$ multilinevar='I have some
> text with '"${placeholders}"'
> in this and some '"${different}"'
> ones '"${here}"' and '"${there}"'.'
$ echo "$multilinevar"
I have some
text with value one
in this and some value two
ones value three and value four.

どちらのソリューションでも、複数行の変数プレースホルダを受け入れることができます。


[a]マニュアルから:

...文字シーケンス\ <newline>は無視され、\は\、$、および文字を引用するために使用する必要があります。 ...

答え2

bashでこれを行うには1つの方法があります。ここでは連想配列を使用するので、最新バージョンが必要です。

template=$(cat << 'END_TEMPLATE'
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}
END_TEMPLATE
)

mapfile -t placeholders < <(grep -Po '(?<=\$\{).+?(?=\})' <<< "$template" | sort -u)

declare -A data
for key in "${placeholders[@]}"; do
    read -p "Enter the '$key' value: " -r data[$key]
done

t=$template
while [[ $t =~ '${'([[:alnum:]_]+)'}' ]]; do
    t=${t//"${BASH_REMATCH[0]}"/"${data[${BASH_REMATCH[1]}]}"}
    #      ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    #      |                    + the value the user entered
    #      + the placeholder in the text
done

echo "$t"

答え3

ユーザー入力が与えられるとone、、twothree

次のコマンドは、提供された${placeholder}すべてのインスタンスを入力に置き換えます。

sed -i 's/${placeholders}/one/g; s/${different}/two/g; s/${here}/three/g' yourTemplateFile

これをbashスクリプトで使用し、シェル変数にユーザー入力を入力すると、1つのコマンドですべての置換が実行されます。

答え4

次のスクリプトを使用してテストし、正常に動作しました。

echo "enter count of userinput required"
read c
for ((i=1;i<=$c;i++))
do
echo "enter the values"
read input_$i
done

awk -v i="$input_1" -v j="$input_2" -v k="$input_3" -v l="$input_4"   '{gsub(/\${placeholders}/,i,$0);gsub(/\${different}/,j,$0);gsub(/\${here}/,k,$0);gsub(/\${there}/,l,$0);print $0}' filename >>filename_tmp && mv filename_tmp filename

関連情報