bash で引用符を保持した文字列補間

bash で引用符を保持した文字列補間

ユーザーの環境変数から置換された値を取得する json の本文をフォーマットする必要があります。 shopt などを使用して、bash スクリプトで json 文字列が正しく置換され、二重引用符が保持/戻されて有効な json になるようにする方法を探しています。 引用符の前処理と二重引用符の使用を試しました。

例:

$ export env_var1=val1
$ export env_var2=val2
$ export args='{"key1": "${env_var1}", "key2": "${env_var2}"}'
$ echo $args #original input
$ eval echo $args #bad output- variables interpolated but quotes lost
Expected output= {"key1": "val1", "key2": "val2"}

編集:ここでの制約は、任意のJSON文字列を事前に知らず、構造や名前が事前にわからないため手動で再フォーマットできないことです。解決する必要はありません。これ特定のケース - これは簡単な例です。この例が代表する任意の文字列の一般的なソリューションを策定しようとしています。キー、値、またはその両方が環境変数である可能性があります。JSON は任意にネストされ、大きくなる可能性があります。

答え1

引用符をエスケープすることもできます:

{\"key1\": \""$env_var1"\", "key2": \""$env_var2"\"}

jq を使うこともできます:

jq -n --arg one "$env_var1" --arg two "$env_var2" '{key1: $one, key2: $two}'

またはジョー:

jo key1="$env_var1" key2="$env_var2"

複雑な JSON オブジェクトには、ヒアドキュメントをよく使用します。

read -rd '' json <<EOF
{
    key1: "$env_var1",
    key2: "$env_var2"
}
EOF
echo "$json"

答え2

原則として、これらの変数を正確に使用すれば、次のように使用できますenvsubst

$ export env_var1=val1
$ export env_var2=val2
$ export args='{"key1": "${env_var1}", "key2": "${env_var2}"}'
$ echo "$args" | envsubst
{"key1": "val1", "key2": "val2"}

ただし、a) に一致するものだけでなく、すべての環境変数が展開されenv_*、b) 有効な JSON にするためにどの内容も引用符で囲まないことに注意してください。たとえばenv_var1='double"quote'、を使用する{"key1": "double"quote", ...と、引用符が壊れた になります。

env_*最初の問題を修正するには、Bash で次のようにして、一致する変数名のリストを含む文字列を取得しますenvsubst

$ echo "$args" | envsubst "$(printf '$%s ' "${!env_@}")"
{"key1": "val1", "key2": "val2"}

(問題は、先頭に$記号が必要なことです。)

2 番目については、変数を に渡す前に前処理するenvsubstか、 を介して渡す必要がありますjq

次のようなコードでは、のような名前のすべての変数--argに対して のオプションが生成され、 がそれらを変数として認識できるように、入力文字列のany が に変更されます(無関係な一致する文字列も変更されることに注意してください)。jqenv_*"${foo}"$foojq

#!/bin/bash

args=(); 
for varname in "${!env_@}"; do
    args+=(--arg "$varname" "${!varname}");
done;
jq -n -c -M "${args[@]}" "$(sed -E -e 's/"\$\{([a-zA-Z0-9_]+)\}"/$\1/g' <<< "$1")"

実行:

$ export env_var1='double"quote' env_var2=foobar
$ bash jsonexpand.sh '{"key1": "${env_var1}", "key2": "${env_var2}"}'
{"key1":"double\"quote","key2":"foobar"}

答え3

シェルがそれを解析しないように、式を引用符で囲む必要があります。簡単なケースでは、

echo '{"key1": "var1", "key2": "var2"}'

変数の補間が必要な場合、これらのオプションのいずれかを使用できます。

printf '{"key1": "%s", "key2": "%s"}\n' "$env_var1" "$env_var2"
echo "{\"key1\": \"$env_var1\", \"key2\": \"$env_var2\"}"
echo '{"key1": "'"$env_var1"', "key2": "'"$env_var2"'"}'

おそらく、最も読みやすいものとして、最初のものをお勧めします。

関連情報