Мне нужно отформатировать тело json, которое получает некоторые значения, заменяемые из переменных среды пользователя. Пытаюсь найти способ через shopt или что-то в этом роде, чтобы строка json была правильно замещена в скрипте bash, но сохраняла/возвращала двойные кавычки, чтобы быть допустимым 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 заранее и не могу переформатировать ее вручную, потому что структура или имена мне заранее не известны. Мне не нужно решатьэтотконкретный случай - это игрушечный пример. Я пытаюсь сформулировать общее решение для произвольной строки, представителем которой является пример. Ключи, значения или и то, и другое могут быть переменными env. 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"}
Но обратите внимание, что это а) расширит любые переменные среды, а не только те, которые соответствуют env_*
, и б) не будет заключать в кавычки никакое содержимое, чтобы сделать его допустимым JSON. Например, с env_var1='double"quote'
, вы получите {"key1": "double"quote", ...
, с нарушенными кавычками.
Чтобы исправить первую проблему, можно сделать что-то вроде этого в Bash, чтобы получить строку, содержащую список имен переменных, env_*
соответствующих envsubst
:
$ echo "$args" | envsubst "$(printf '$%s ' "${!env_@}")"
{"key1": "val1", "key2": "val2"}
(проблема в том, что для этого требуются ведущие $
знаки.)
Во втором случае вам придется предварительно обработать переменные перед передачей их в envsubst
или передать их через jq
.
Что-то вроде этого сгенерирует --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
Вам нужно заключить выражение в кавычки, чтобы оболочка не анализировала его. В тривиальном случае,
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"'"}'
Я бы, пожалуй, порекомендовал первую из них как наиболее читаемую.