我必須格式化 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"
我經常使用heredocs來處理複雜的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"}
(問題是它需要引導$
標誌。)
對於第二個,您必須在將變數傳遞給envsubst
或將它們傳遞給之前對變數進行預處理jq
。
像這樣的東西將為所有名為 like 的變量生成--arg
選項,並將輸入字串中的任何一個更改為變量,以便將它們識別為變量(請注意,它還會更改任何不相關的匹配字串) :jq
env_*
"${foo}"
$foo
jq
#!/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
您需要引用該表達式,以便 shell 不會解析它。在這個微不足道的案例中,
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"'"}'
我可能會推薦其中第一個,因為它是最具可讀性的。