Por que o conteúdo JSON do heredoc não é analisável?

10

Eu tenho um fragmento JSON.

O seguinte não funciona:

VALUE=<<PERSON
{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "[email protected]"  
}
PERSON
echo -n "$VALUE" | python -m json.tool

O resultado é:

No JSON object could be decoded

Fazendo o mesmo com jq , i. e.

echo -n "$VALUE" | jq '.'

Não há saída.

Existe o mesmo comportamento para o seguinte:

VALUE=<<PERSON
'{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "[email protected]"  
}'
PERSON
echo -n "$VALUE" | python -m json.tool

Resposta:

No JSON object could be decoded

Mas os seguintes trabalhos:

VALUE='{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "[email protected]"
}'
echo -n "$VALUE" | jq '.'
echo -n "$VALUE" | python -m json.tool
    
por Jim 11.04.2018 / 12:59

4 respostas

19

VALUE=<<PERSON
some data
PERSON

echo "$VALUE"

Nenhuma saída.

Um documento aqui é um redirecionamento , você não pode redirecionar para uma variável.

Quando a linha de comando é analisada, os redirecionamentos são tratados em uma etapa separada das atribuições de variáveis. Seu comando é, portanto, equivalente a (observe o espaço)

VALUE= <<PERSON
some data
PERSON

Isto é, ele atribui uma string vazia à sua variável, então redireciona a entrada padrão da string here para o comando (mas não há comando, então nada acontece).

Note que

<<PERSON
some data
PERSON

é válido, como é

<somefile

É apenas que não existe nenhum comando cujo fluxo de entrada padrão possa ser configurado para conter os dados, por isso é apenas perdido.

Isso funcionaria, no entanto:

VALUE=$(cat <<PERSON
some data
PERSON
)

Aqui, o comando que recebe o documento here é cat e o copia para sua saída padrão. Isto é então o que é atribuído à variável por meio da substituição do comando.

No seu caso, você poderia usar

python -m json.tool <<END_JSON
JSON data here
END_JSON

sem dar o passo extra de armazenar os dados em uma variável.

    
por 11.04.2018 / 13:05
10

Porque a variável não está sendo definida pelo seu heredoc:

$ VALUE=<<PERSON  
> {    
>   "type": "account",  
>   "customer_id": "1234",  
>   "customer_email": "[email protected]",  
> }  
> PERSON
$ echo "$VALUE" 

$

Se você quiser usar um heredoc para atribuir um valor a uma variável, precisa de algo como:

$ read -d '' -r VALUE <<PERSON  
{    
  "type": "account",  
  "customer_id": "1234",  
  "customer_email": "[email protected]",  
}   
PERSON
    
por 11.04.2018 / 13:05
4

É porque a maneira como você definiu um aqui-doc para usar com um JSON está errada. Você precisa usá-lo como

VALUE=$(cat <<EOF
{  
  "type": "account",  
  "customer_id": "1234",  
  "customer_email": "[email protected]",  
}
EOF
)

e fazendo printf "$VALUE" deve despejar o JSON como esperado.

    
por 11.04.2018 / 13:05
3

Heredocs e variáveis não se misturam bem ou pelo menos não dessa maneira. Você pode tanto ...

Passar o heredoc como a entrada padrão de um aplicativo

python -m json.tool <<PERSON  
{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "[email protected]",
}
PERSON

ou…

Armazenar texto de várias linhas em uma variável do shell

VALUE='{
  "type": "account",
  "customer_id": "1234",
  "customer_email": "[email protected]",
}'

Eu usei aspas simples para evitar a necessidade de escapar das aspas duplas internas. Claro que você também pode usar aspas duplas, e. g. se você precisar expandir parâmetros:

VALUE="{
  \"type\": \"account\",
  \"customer_id\": ${ID},
  \"customer_email\": \"${EMAIL}\",
}"

Então você pode usar o valor da variável mais tarde.

echo -n "$VALUE" | python -m json.tool
    
por 11.04.2018 / 14:10