字串插值在 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"

我經常使用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選項,並將輸入字串中的任何一個更改為變量,以便將它們識別為變量(請注意,它還會更改任何不相關的匹配字串) :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

您需要引用該表達式,以便 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"'"}'

我可能會推薦其中第一個,因為它是最具可讀性的。

相關內容