149 votes

Comment formater une chaîne JSON comme une table en utilisant jq?

Juste commencé avec l'écriture de scripts Bash et je suis tombé sur jq à travailler avec JSON.

J'ai besoin de transformer une chaîne JSON comme ci-dessous un tableau pour la sortie dans le terminal.

[{
    "name": "George",
    "id": 12,
    "email": "george@domain.com"
}, {
    "name": "Jack",
    "id": 18,
    "email": "jack@domain.com"
}, {
    "name": "Joe",
    "id": 19,
    "email": "joe@domain.com"
}]

Ce que je veux afficher dans le terminal:

ID        Name
=================
12        George
18        Jack
19        Joe

Remarquez comment je ne veux pas afficher l'e-mail de propriété pour chaque ligne, de sorte que le jq commande doit impliquer un filtrage. La suite donne-moi une simple liste de noms et id:

list=$(echo "$data" | jq -r '.[] | .name, .id')
printf "$list"

Le problème c'est que je ne peut pas l'afficher comme une table. Je sais jq a certaines options de mise en forme, mais pas aussi bon que les options que j'ai lors de l'utilisation d' printf. Je pense que je veux obtenir ces valeurs dans un tableau à laquelle je peux ensuite faire une boucle par moi-même à faire la mise en forme...? Les choses que j'ai essayé de me donner des résultats différents, mais jamais ce que je veux vraiment.

Quelqu'un peut me pointer dans la bonne direction?

179voto

peak Points 71

L'utilisation du filtre @tsv a beaucoup à recommander, principalement parce qu'il gère de nombreux "cas de bord" de manière standard:

 .[] | [.id, .name] | @tsv
 

L'ajout des en-têtes peut se faire comme suit:

 jq -r '["ID","NAME"], ["--","------"], (.[] | [.id, .name]) | @tsv'
 

Le résultat:

 ID  NAME
--  ------
12  George
18  Jack
19  Joe
 

114voto

sjsam Points 186

Pourquoi pas quelque chose comme :

echo '[{
    "name": "George",
    "id": 12,
    "email": "george@domain.com"
}, {
    "name": "Jack",
    "id": 18,
    "email": "jack@domain.com"
}, {
    "name": "Joe",
    "id": 19,
    "email": "joe@domain.com"
}]' | jq -r '.[] | "\(.id)\t\(.name)"'

Sortie

12  George
18  Jack
19  Joe

Edit 1 : Pour précision, la mise en forme utiliser des outils comme awk

 echo '[{
    "name": "George",
    "id": 12,
    "email": "george@domain.com"
}, {
    "name": "Jack",
    "id": 18,
    "email": "jack@domain.com"
}, {
    "name": "Joe",
    "id": 19,
    "email": "joe@domain.com"
}]' | jq -r '.[] | [.id, .name] | @csv' | awk -v FS="," 'BEGIN{print "ID\tName";print "============"}{printf "%s\t%s%s",$1,$2,ORS}'
ID  Name
============
12  "George"
18  "Jack"
19  "Joe"

Edit 2 : En réponse à

Il n'y a aucun moyen que je peux obtenir une variable contenant un tableau de droite de jq?

Pourquoi pas?

Un peu impliquées exemple( en fait modifié de la vôtre ) où e-mail est changé pour un tableau le démontre

echo '[{
    "name": "George",
    "id": 20,
    "email": [ "george@domain1.com" , "george@domain2.com" ]
}, {
    "name": "Jack",
    "id": 18,
    "email": [ "jack@domain3.com" , "jack@domain5.com" ]
}, {
    "name": "Joe",
    "id": 19,
    "email": [ "joe@domain.com" ]
}]' | jq -r '.[] | .email'

Sortie

[
  "george@domain1.com",
  "george@domain2.com"
]
[
  "jack@domain3.com",
  "jack@domain5.com"
]
[
  "joe@domain.com"
]

0voto

Micha Wiedenmann Points 3357

Si les valeurs ne contiennent pas d'espaces, cela peut être utile:

 read -r -a data <<<'name1 value1 name2 value2'

echo "name value"
echo "=========="

for ((i=0; i<${#data[@]}; i+=2)); do
  echo ${data[$i]} ${data[$((i+1))]}
done
 

Sortie

 name value
==========
name1 value1
name2 value2
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X