¿Cómo hago eco de una llave JSON vacía como valor predeterminado?

11

Parece que no puedo obtener un JSON vacío {}para hacer eco si falta un envvar. O tengo un seguimiento }en la salida si está configurado, o se muestra el escape.

bash-3.2$ unset X
bash-3.2$ echo "${X:-{}}"
{}
bash-3.2$ X=y
bash-3.2$ echo "${X:-{}}"
y}
bash-3.2$ echo "${X:-{\}}"
y
bash-3.2$ unset X
bash-3.2$ echo "${X:-{\}}"
{\}
bash-3.2$ echo "${X:-'{}'}"
'{}'
bash-3.2$ X=z
bash-3.2$ echo "${X:-'{}'}"
z

¿Cómo escapo correctamente?

Nick T
fuente
Interesante, pero con bash 4.3 echo "${X:-{\}}"funcionó bien.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy Eso se solucionó en 4.2; Recuerdo algunas discusiones sobre la cita de expansiones de palabras después de operadores de expansión de parámetros para cumplir con el estándar POSIX.
chepner

Respuestas:

14

Cita tus frenillos:

bash-3.2$ echo "${X:-"{}"}"
{}
bash-3.2$ X=y
bash-3.2$ echo "${X:-"{}"}"
y
bash-3.2$ unset X
bash-3.2$ echo "${X:-"{}"}"
{}

Aquí se requieren comillas dobles internas , lo que parece divertido pero está sintácticamente bien.

Las comillas simples no funcionarán, y no estoy completamente seguro de por qué no. Esta es una cita real anidada, no end-and-resume, que puede verificar colocando espacios. Sin embargo, Double funcionará bien.

Michael Homer
fuente
Creo que esta es la oración relevante de la especificación POSIX: "El carácter '}' que delimita las siguientes modificaciones de expansión de parámetros se determinará como se describió anteriormente en esta sección y en comillas dobles". Interpreto que esto significa que lo wordsiguiente :-debe estar específicamente entre comillas dobles, por "${X:-'{}'}"lo que literalmente va ${X:-'{}seguido de '}. Por qué la especificación es tan específica no me queda claro.
chepner
(La frase mencionada por "descrito anteriormente" es "La llave de cierre correspondiente se determinará por los niveles de recuento Brace, saltando sobre las cadenas entre comillas cerradas, y sustituciones de comando.")
chepner
9

Puede hacer trampa y establecer una variable para que sea el resultado vacío, y evitar los problemas de citas

$ def="{}"
$ echo ${X:-$def}
{}
$ X=y
$ echo ${X:-$def}
y
$ unset X
$ echo ${X:-$def}
{}
$ 
Stephen Harris
fuente
5

Lo que hago con frecuencia es utilizar valores hexadecimales para los caracteres a través de printf:

bash-4.3$ echo "${X:-$(printf '\x7B\x7D')}"
{}
bash-4.3$ X="something"
bash-4.3$ echo "${X:-$(printf '\x7B\x7D')}"
something

Ligeramente detallado, pero funciona sin demasiado estrés sobre las citas.

Sergiy Kolodyazhnyy
fuente