Retour sur la function map()
de la commande jq et on se propose de construire la réciproque de la sortie de la commande column.
Dans lâarticle đ JSON et la commande column on a vu que la commande column lorsquâon utilise le format JSON donnait un rĂ©sultat du type :
{
"table": [
{
"col1": "value1-1",
"col2": "value2-1",
"col3": "value3-1"
},{
"col1": "value1-2",
"col2": "value2-2 beaucoup plus longue que les autres",
"col3": "value3-2"
}
]
}
On simplifiera cette sortie Ă lâaide de :
jq '.table'
et dans la suite, on considéra, le code JSON suivant :
[
{
"col1": "value1-1",
"col2": "value2-1",
"col3": "value3-1"
},
{
"col1": "value1-2",
"col2": "value2-2 beaucoup plus longue que les autres",
"col3": "value3-2"
}
]
Que lâon peut construire Ă lâaide de :
echo '[{"col1":"value1-1","col2":"value2-1","col3":"value3-1"},{"col1":"value1-2","col2":"value2-2 beaucoup plus longue que les autres","col3":"value3-2"}]'
Reconstruire les colonnes
SĂ©paration des lignes
On va dâabord extraire chaque ligne Ă lâaide .[]
(on ajoute le drapeau --raw-output
/ -r
afin de mieux comprendre le résultat affiché):
echo '[{"col1":"value1-1","col2":"value2-1","col3":"value3-1"},{"col1":"value1-2","col2":"value2-2 beaucoup plus longue que les autres","col3":"value3-2"}]' |
jq -c '.[]'
On a alors un flux qui ressemble à ceci :
{"col1":"value1-1","col2":"value2-1","col3":"value3-1"}
{"col1":"value1-2","col2":"value2-2 beaucoup plus longue que les autres","col3":"value3-2"}
SĂ©paration des colonnes dâune ligne
Ensuite sur chacune des lignes, pour ne rĂ©cupĂ©rer la uniquement la valeur, on va dâabord sĂ©parer les clĂ©s et des valeurs de chaque colonne Ă lâaide de la mĂ©thode to_entries
suivi de .[].value
.
echo '{"col1":"value1-1","col2":"value2-1","col3":"value3-1"}' |
jq -r 'to_entries'
La fonction to_entries
produira pour chaque ligne quelque chose comme ça :
[
{
"key": "col1",
"value": "value1-1"
},
{
"key": "col2",
"value": "value2-1"
},
{
"key": "col3",
"value": "value3-1"
}
]
Pour ne garder que la valeur, on sépare les éléments du tableau et on ne prend que le champ value
, mais comme pour la suite on a besoin dâun tableau on encadre le rĂ©sultat avec [
et ]
 :
echo '[{"key":"col1","value":"value1-1"},{"key":"col2","value":"value2-1"},{"key":"col3","value":"value3-1"}]' |
jq '[.[].value]'
Ici on remarque que lâon met dans un tableau ([]
) le rĂ©sultat de quelque chose qui provient des Ă©lĂ©ments dâun tableau (.[]
). Ceci correspond typiquement au cas dâusage de la fonction map()
.
Avec la fonction map()
on Ă©crira :
echo '[{"key":"col1","value":"value1-1"},{"key":"col2","value":"value2-1"},{"key":"col3","value":"value3-1"}]' |
jq 'map( .value )'
Sans surprise on la liste des valeurs :
[
"value1-1",
"value2-1",
"value3-1"
]
Il ne reste plus quâĂ demander Ă jq Ă nous mettre ce tableau en colonnes. Cela se fait Ă lâaide de la mĂ©thode @tsv
(âTabulation Separated Valuesâ):
echo '["value1-1","value2-1","value3-1"]' |
jq --raw-output @tsv
On a alors ceci :
value1-1 value2-1 value3-1
En marge :
-
Le drapeau `--raw-output` / `-r`
-
--raw-output
/-r
 :Avec cette option, si le rĂ©sultat du filtre est une chaĂźne de caractĂšres, il sera Ă©crit directement sur la sortie standard plutĂŽt que dâĂȘtre formatĂ© comme une chaĂźne JSON avec des guillemets. Cela peut ĂȘtre utile pour faire dialoguer les filtres jq avec des systĂšmes non basĂ©s sur JSON*.
-
--raw-output0
 :Comme
-r
mais jq affichera le caractĂšre NUL au lieu dâun saut de ligne aprĂšs chaque sortie. De mĂȘme pour les autres caractĂšres de formatage comme la tabulation.
-
RĂ©sumons
AprĂšs lâanalyse de ce quâil se passe ligne par ligne, on va faire le calcul complet pour le flux JSON initial :
echo '[{"col1":"value1-1","col2":"value2-1","col3":"value3-1"},{"col1":"value1-2","col2":"value2-2 beaucoup plus longue que les autres","col3":"value3-2"}]' |
jq -r '.[] | to_entries | map( .value ) | @tsv'
Voici ce que ça donne :
value1-1 value2-1 value3-1
value1-2 value2-2 beaucoup plus longue que les autres value3-2
On note que pour un affichage ce nâest pas parfait, puisquâon a un dĂ©calage dans les colonnes.
Fignolons
On a vu dans le billet đ JSON et la commande column la commande column que lâon peut utiliser ici dans son usage principal, comme suit :
echo '[{"col1":"value1-1","col2":"value2-1","col3":"value3-1"},{"col1":"value1-2","col2":"value2-2 beaucoup plus longue que les autres","col3":"value3-2"}]' |
jq -r '.[] | to_entries | map( .value ) | @tsv' |
column --table --separator $'\t'
Notez quâil faut dĂ©finir le sĂ©parateur comme Ă©tant le caractĂšre de tabulation et cela sâĂ©crit en bash : $'\t'
.
On a un résultat nettement plus satisfaisant :
value1-1 value2-1 value3-1
value1-2 value2-2 beaucoup plus longue que les autres value3-2
Liens
- đ Aide-mĂ©moire jq : map(x),
- đ JSON et la commande column,
- La FAQ de jq en anglais,
- Le manuel de jq en anglais (Vous pouvez choisir la version de jq).
኿