String-Interpolation unter Beibehaltung von Anführungszeichen in Bash

String-Interpolation unter Beibehaltung von Anführungszeichen in Bash

Ich muss den Hauptteil eines JSON formatieren, in dem einige Werte aus Benutzerumgebungsvariablen ersetzt werden. Ich versuche, über shopt oder so etwas eine Möglichkeit zu finden, damit die JSON-Zeichenfolge im Bash-Skript korrekt ersetzt wird, aber die Anführungszeichen beibehalten/zurückgesetzt werden, um ein gültiges JSON zu sein. Habe versucht, Anführungszeichen vorzuverarbeiten und doppelte Anführungszeichen zu verwenden.

Beispiel:

$ 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"}

Bearbeiten: Meine Einschränkung hier ist, dass ich den beliebigen JSON-String nicht im Voraus kenne und ihn nicht manuell neu formatieren kann, da mir die Struktur oder die Namen nicht im Voraus bekannt sind. Ich muss nicht lösenDasSonderfall – es ist ein Spielzeugbeispiel. Ich versuche, eine generische Lösung für eine beliebige Zeichenfolge zu formulieren, für die das Beispiel repräsentativ ist. Die Schlüssel, Werte oder beide könnten Umgebungsvariablen sein. Das JSON könnte beliebig verschachtelt und groß sein.

Antwort1

Sie können die Anführungszeichen weglassen:

{\"key1\": \""$env_var1"\", "key2": \""$env_var2"\"}

Sie könnten jq verwenden:

jq -n --arg one "$env_var1" --arg two "$env_var2" '{key1: $one, key2: $two}'

Oderjo:

jo key1="$env_var1" key2="$env_var2"

Ich verwende häufig Heredocs für komplexe JSON-Objekte:

read -rd '' json <<EOF
{
    key1: "$env_var1",
    key2: "$env_var2"
}
EOF
echo "$json"

Antwort2

Im Prinzip könnten Sie mit genau diesen Variablen Folgendes verwenden envsubst:

$ export env_var1=val1
$ export env_var2=val2
$ export args='{"key1": "${env_var1}", "key2": "${env_var2}"}'
$ echo "$args" | envsubst
{"key1": "val1", "key2": "val2"}

Beachten Sie jedoch, dass a) alle Umgebungsvariablen erweitert werden, nicht nur diejenigen, die mit übereinstimmen env_*, und b) keine Inhalte in Anführungszeichen gesetzt werden, um sie in gültiges JSON umzuwandeln. Mit env_var1='double"quote'erhalten Sie beispielsweise {"key1": "double"quote", ...mit fehlerhaften Anführungszeichen.

Um das erste Problem zu beheben, können Sie in Bash Folgendes tun, um einen String mit einer Liste der Variablennamen zu erhalten, die env_*mit Folgendem übereinstimmen envsubst:

$ echo "$args" | envsubst "$(printf '$%s ' "${!env_@}")"
{"key1": "val1", "key2": "val2"}

(das Problem besteht darin, dass die $Vorzeichen erforderlich sind.)

Im zweiten Fall müssten Sie die Variablen vor der Weitergabe an vorverarbeiten envsubstoder sie durch weitergeben jq.

--argSo etwas wie das hier würde Optionen für jqalle Variablen mit Namen wie generieren env_*und alle "${foo}"aus der Eingabezeichenfolge in ändern, $foosodass jqsie als Variablen erkannt werden (beachten Sie, dass dadurch auch alle nicht verwandten übereinstimmenden Zeichenfolgen geändert würden):

#!/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")"

Ausführen mit:

$ export env_var1='double"quote' env_var2=foobar
$ bash jsonexpand.sh '{"key1": "${env_var1}", "key2": "${env_var2}"}'
{"key1":"double\"quote","key2":"foobar"}

Antwort3

Sie müssen den Ausdruck in Anführungszeichen setzen, damit die Shell ihn nicht analysiert. Im trivialen Fall

echo '{"key1": "var1", "key2": "var2"}'

In Ihrem Fall, in dem Sie eine Interpolation von Variablen benötigen, kann jede dieser Optionen funktionieren

printf '{"key1": "%s", "key2": "%s"}\n' "$env_var1" "$env_var2"
echo "{\"key1\": \"$env_var1\", \"key2\": \"$env_var2\"}"
echo '{"key1": "'"$env_var1"', "key2": "'"$env_var2"'"}'

Ich würde wahrscheinlich das erste davon empfehlen, da es sich am besten lesen lässt.

verwandte Informationen