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

我可能会推荐其中第一个,因为它是最具可读性的。

相关内容