interpolação de strings preservando aspas no bash

interpolação de strings preservando aspas no bash

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 --argopções para jqtodas as variáveis ​​​​nomeadas como env_*e alteraria qualquer "${foo}"uma da string de entrada para $fooreconhecê 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.

informação relacionada