Como ecoar um colchete JSON vazio como valor padrão?

11

Não consigo obter um JSON vazio {}para ecoar se estiver faltando um envvar. Ou tenho um rastro }na saída, se definido, ou a fuga é exibida.

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

Como faço para escapar corretamente?

Nick T
fonte
Interessante, mas com o bash 4.3 echo "${X:-{\}}"funcionou muito bem.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy Isso foi corrigido no 4.2; Lembro-me de uma discussão sobre a citação de expansões de palavras, seguindo operadores de expansão de parâmetros para estar em conformidade com o padrão POSIX.
Chepner #

Respostas:

14

Cite seus aparelhos:

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:-"{}"}"
{}

As aspas duplas internas são obrigatórias aqui, o que parece engraçado, mas é sintaticamente correto.

As aspas simples não funcionam, e não sei bem por que não. Essa é uma citação aninhada real, não final e resumo, que você pode verificar colocando espaços. No entanto, o Double funcionará bem.

Michael Homer
fonte
Penso que esta é a sentença relevante da especificação POSIX: "O caractere '}' que delimita as seguintes modificações de expansão de parâmetros deve ser determinado conforme descrito anteriormente nesta seção e entre aspas duplas." Eu interpreto isso como significando que o wordseguinte :-deve ser especificamente entre aspas duplas, portanto "${X:-'{}'}"é literalmente ${X:-'{}seguido por '}. Por que a especificação é tão específica não está clara para mim.
Chepner #
(A sentença mencionada por "descrito anteriormente" é "A chave de fechamento correspondente será determinada pela contagem dos níveis da chave, passando por cima das strings entre aspas e substituindo comandos.")
chepner
9

Você pode trapacear e definir uma variável para ser o resultado vazio e evitar os problemas de cotação.

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

O que frequentemente faço é usar valores hexadecimais para caracteres via printf:

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

Um pouco detalhado, mas funciona sem muito estresse sobre as aspas.

Sergiy Kolodyazhnyy
fonte