cClaude.rocks ☕ Le blog

[Nouvelles technologies du libre, sciences et coups de gueule…]

Menu

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

኿


â„č 2006 - 2024 | 🏠 Accueil du domaine | 🏡 Accueil du blog