Tenho que formatar o corpo de um json que obtém alguns valores substituídos das variáveis de ambiente do usuário. Tentando encontrar uma maneira via shopt ou algo assim para que a string json seja substituída corretamente no script bash, mas preserve/coloque de volta as aspas duplas para ser um json válido. Tentei pré-processar cotações e aspas duplas.
Exemplo:
$ 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"}
Editar: minha restrição aqui é que não conheço a string json arbitrária com antecedência e não posso reformatá-la manualmente porque a estrutura ou os nomes não são conhecidos por mim com antecedência. Eu não preciso resolveressecaso específico - é um exemplo de brinquedo. Estou tentando formular uma solução genérica para uma sequência arbitrária da qual o exemplo é representativo. As chaves, valores ou ambos podem ser variáveis env. O json pode ser aninhado e grande arbitrariamente.
Responder1
Você poderia escapar das aspas:
{\"key1\": \""$env_var1"\", "key2": \""$env_var2"\"}
Você poderia usar jq:
jq -n --arg one "$env_var1" --arg two "$env_var2" '{key1: $one, key2: $two}'
Oujo:
jo key1="$env_var1" key2="$env_var2"
Muitas vezes uso heredocs para objetos json complexos:
read -rd '' json <<EOF
{
key1: "$env_var1",
key2: "$env_var2"
}
EOF
echo "$json"
Responder2
Em princípio, com essas variáveis exatas, você poderia usar envsubst
:
$ export env_var1=val1
$ export env_var2=val2
$ export args='{"key1": "${env_var1}", "key2": "${env_var2}"}'
$ echo "$args" | envsubst
{"key1": "val1", "key2": "val2"}
Mas observe que a) expandirá quaisquer variáveis de ambiente, não apenas aquelas correspondentes env_*
, eb) não citará nenhum conteúdo para transformá-los em JSON válido. Por exemplo, com env_var1='double"quote'
, você obtém {"key1": "double"quote", ...
, com citações quebradas.
Para corrigir esse primeiro problema, você poderia fazer algo assim no Bash, para obter uma string contendo uma lista dos nomes de variáveis correspondentes env_*
a envsubst
:
$ echo "$args" | envsubst "$(printf '$%s ' "${!env_@}")"
{"key1": "val1", "key2": "val2"}
(o problema é que requer os $
sinais iniciais.)
Para o segundo, você teria que pré-processar as variáveis antes de passá-las para envsubst
, ou passá-las para jq
.
Algo assim geraria --arg
opções para jq
todas as variáveis nomeadas como env_*
e alteraria qualquer "${foo}"
uma da string de entrada para $foo
reconhecê jq
-las como variáveis (observe que isso também alteraria quaisquer strings correspondentes não relacionadas):
#!/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")"
Correr com:
$ export env_var1='double"quote' env_var2=foobar
$ bash jsonexpand.sh '{"key1": "${env_var1}", "key2": "${env_var2}"}'
{"key1":"double\"quote","key2":"foobar"}
Responder3
Você precisa citar a expressão para que o shell não a analise. No caso trivial,
echo '{"key1": "var1", "key2": "var2"}'
No seu caso, onde você precisa de interpolação de variáveis, qualquer uma dessas opções pode funcionar
printf '{"key1": "%s", "key2": "%s"}\n' "$env_var1" "$env_var2"
echo "{\"key1\": \"$env_var1\", \"key2\": \"$env_var2\"}"
echo '{"key1": "'"$env_var1"', "key2": "'"$env_var2"'"}'
Eu provavelmente recomendaria o primeiro deles como o mais legível.