Considere um exemplo artificial usando um objeto JSON como este, onde eu quero extrair os campos id
, firstname
e relacionados lastname
para cada um dos muitos objetos de array em variáveis de shell para processamento posterior (não JSON).
{
"customers": [
{
"id": 1234,
"firstname": "John",
"lastname": "Smith",
"other": "fields",
"are": "present",
"here": "etc."
},
{
"id": 2468,
"firstname": "Janet",
"lastname": "Green",
"other": "values",
"are": "probably",
"here": "maybe"
}
]
}
Para dados simples posso usar isto,
jq -r '.customers[] | (.id + " " + .firstname + " " + .lastname)' <data.json |
while IFS=' ' read id firstname lastname
do
# More processing, but omitted for the example
printf '%s -- %s -- %s\n' "$id" "$firstname" "$lastname"
done
Saída
1234 -- John -- Smith
2468 -- Janet -- Green
mas é claro que isso falhará com firstname
valores de duplo sentido, como Anne Marie
. Alterar o separador para outro caractere, como #
parece mais uma falsificação do que uma solução, mas pode ser aceitável.
Para situações mais complexas, eu poderia escolher a lista de id
valores e então trocar velocidade por precisão voltando para extrair os elementos firstname
and correspondentes lastname
. Algo assim:
jq -r '.customers[].id' <data.json |
while IFS= read id
do
block=$(jq -r --arg id "$id" '.customers[] | select(.id == $id)' <data.json);
firstname=$(jq -r '.firstname' <<<"$block")
lastname=$(jq -r '.lastname' <<<"$block")
# More processing, but omitted for the example
printf '%s -- %s -- %s\n' "$id" "$firstname" "$lastname"
done
Saída
1234 -- John -- Smith
2468 -- Janet -- Green
No entanto, nenhuma delas é correta e eficiente. Embora eu não vá executar o código real em alta frequência, gostaria de entender se há uma maneira mais apropriada de obter múltiplos elementos de dados de forma segura e eficiente de uma estrutura de objeto JSON para variáveis de shell?