Linux & Bash · Chapitre 8

8. JQ

Les commandes Linux manipulent beaucoup de texte, mais les outils modernes renvoient souvent des données structurées au format JSON. jq est un outil en ligne de commande qui permet de lire, filtrer, transformer et reconstruire du JSON directement dans un terminal.

Fil conducteur : recevoir du JSON → parcourir sa structure → sélectionner les champs utiles → enchaîner des filtres → reconstruire un résultat → appliquer des opérations et des fonctions.
Repère : avant d’écrire un filtre jq, il faut identifier la structure de l’entrée : objet, tableau, puis champs imbriqués.

Le jeu de données utilisé par Liora est un tableau JSON contenant des objets. Cette distinction est essentielle : [] sert à parcourir les éléments d’un tableau, tandis qu’un nom de champ comme .name permet d’accéder à une propriété d’un objet.

8.1.2 Tableau et objet JSON

jq reçoit du JSON en entrée et produit du JSON ou des valeurs extraites en sortie. Il est particulièrement adapté aux sorties d’API et aux outils d’administration qui renvoient des données structurées.

8.1.1 jq travaille sur des données JSON

8.1 Comprendre ce que jq manipule

8.2 Comprendre les filtres jq

8.2.1 Le point . : identité

cat people.json | jq .

Le filtre . reçoit l’objet d’entrée et le restitue. Il permet ici d’afficher proprement le JSON.

8.2.2 Parcourir un tableau avec []

Comme le document principal est un tableau, .[] permet d’en parcourir les éléments. Un champ peut ensuite être sélectionné, par exemple .name ou .birth_year.

cat people.json | jq '.[] | .birth_year'

8.2.3 Sélectionner une tranche

Le slicing permet de prendre une partie du tableau. Pour les cinq premiers éléments :

cat people.json | jq '.[0:5]'

8.2.4 Appliquer plusieurs filtres avec la virgule

cat people.json | jq '.[].name, .[].height'

La virgule applique plusieurs filtres à la même entrée : ici tous les noms, puis toutes les tailles.

8.2.5 Enchaîner les traitements avec le pipe

Comme dans Bash, le pipe transmet la sortie d’une étape à la suivante :

cat people.json | jq '.[] | .birth_year'
Différence importante : le premier |, hors des quotes, est le pipe du shell entre cat et jq. Le second, à l’intérieur de l’expression jq, enchaîne deux filtres jq.

8.2.6 Filtrer avec select()

select(condition) conserve uniquement les valeurs pour lesquelles la condition est vraie. Sur un tableau, on commence généralement par .[] afin d’envoyer chaque objet vers select().

Considérons le fichier utilisateurs.json :

[
  { "nom": "Axel", "age": 42, "actif": true },
  { "nom": "Claire", "age": 42, "actif": true },
  { "nom": "Lina", "age": 17, "actif": false }
]

Conserver les personnes majeures :

jq '.[] | select(.age >= 18)' utilisateurs.json

Conserver les personnes majeures et actives :

jq '.[] | select(.age >= 18 and .actif == true)' utilisateurs.json

Filtrer, puis extraire uniquement le nom sans guillemets JSON :

jq -r '.[] | select(.age >= 18) | .nom' utilisateurs.json

Reconstituer un tableau JSON contenant uniquement les résultats :

jq '[.[] | select(.age >= 18)]' utilisateurs.json
ÉlémentRôle
.[]Parcourt les objets du tableau.
|Transmet chaque résultat au filtre suivant.
select(condition)Ne conserve que les objets qui respectent la condition.
.nomExtrait ensuite la propriété nom.
-rAffiche les chaînes sans guillemets JSON.
[ ... ]Regroupe les résultats dans un nouveau tableau JSON.
Lecture de gauche à droite : .[] | select(.actif == true) | .nom signifie « parcourir les utilisateurs, garder les actifs, puis afficher leur nom ».

8.3 Construire de nouveaux résultats

8.3.1 Construire un tableau

Les crochets permettent de créer un nouveau tableau à partir des champs sélectionnés :

cat people.json | jq '.[] | [.name, .birth_year, .mass, .height]'

8.3.2 Construire un objet

Les accolades construisent un nouvel objet JSON :

cat people.json | jq '.[] | {name, height, films: .films[]}'

Un champ du premier niveau peut être repris directement avec son nom. Lorsqu’on veut construire une clé avec une expression différente, on écrit nouvelle_cle: expression.

8.3.3 Construire un document plus complexe

Cet exemple combine plusieurs mécanismes sur les dix premiers objets :

cat people.json | jq '.[:10] | .[] | {name, birth_year, mass, species: .species[], details: [.homeworld, .vehicles, .starships[]]}'

On combine ici slicing, parcours du tableau, construction d’objet et construction d’un tableau imbriqué.

8.4 Utiliser les opérateurs

8.4.1 Addition : +

Le comportement dépend du type des valeurs :

TypeEffet de +
NombresAddition arithmétique.
TableauxConcaténation des tableaux.
ChaînesConcaténation des chaînes.
ObjetsFusion des objets ; en cas de clé identique, la valeur de droite est conservée.
jq '.[0].id + .[1].id' people.json
jq '.[0].species + .[1].species' people.json
jq '.[0].name + .[1].name' people.json
jq '.[] | {name, birth_year, mass} + {name, height}' people.json

8.4.2 Soustraction : -

Elle permet une soustraction numérique et peut aussi retirer des valeurs d’un tableau :

jq '.[0].films - ["http://swapi.co/api/films/6/", "http://swapi.co/api/films/7/"]' people.json

8.4.3 Multiplication : *

Elle multiplie des nombres ; appliquée entre une chaîne et un nombre, elle répète la chaîne :

jq '.[10].id * 15' people.json
jq '.[0].name * 3' people.json

8.4.4 Division : /

Outre la division numérique, / peut découper une chaîne selon un séparateur :

jq '.[0].name / "e"' people.json

Luke Skywalker devient alors un tableau contenant les morceaux séparés par la lettre e.

8.5 Regrouper et compter avec group_by et length

8.5.1 Regrouper les objets

cat people.json | jq 'group_by(.eye_color)'

group_by(.eye_color) crée plusieurs tableaux, un par valeur de eye_color.

8.5.2 Compter les éléments de chaque groupe

cat people.json | jq 'group_by(.eye_color)[] | {eye_color: .[0].eye_color, count: length}'

length renvoie ici le nombre d’objets du groupe. .[0].eye_color récupère la couleur sur un seul élément représentatif du groupe ; utiliser .[].eye_color produirait au contraire un résultat pour chaque personnage du groupe.

8.6 Le chemin logique avec jq

BesoinÉcriture jq
Afficher l’entrée.
Parcourir un tableau.[]
Lire un champ.name
Prendre une tranche.[0:5]
Enchaîner des filtres|
Filtrer selon une conditionselect(condition)
Appliquer plusieurs filtres,
Construire un tableau[...]
Construire un objet{...}
Regroupergroup_by(...)
Compterlength
Importance pour un DevOps : de nombreuses API et commandes d’infrastructure renvoient du JSON. jq permet d’en extraire précisément une valeur ou de transformer la sortie avant de la transmettre à une autre étape d’un script ou d’un pipeline. Le cours souligne également son intérêt dans les traitements ETL.