Recherche de site Web

Comment analyser un fichier json à partir de la ligne de commande Linux à l’aide de jq


Le format JSON (JavaScript Object Notation) est largement utilisé pour représenter les structures de données, et est fréquemment utilisé pour échanger des données entre les différentes couches d’une application, ou par l’utilisation d’appels API. Nous savons probablement comment interagir avec des données au format json avec les langages de programmation les plus utilisés tels que l’analyse de JSON avec python, mais que se passe-t-il si nous devons interagir avec eux à partir de la ligne de commande ou dans un script bash ? Dans cet article, nous allons voir comment nous pouvons accomplir une telle tâche en utilisant l’utilitaire jq et nous allons apprendre son utilisation de base.

Dans ce tutoriel, vous allez apprendre :

  • Comment installer jq dans les distributions Linux les plus utilisées ou le compiler à partir des sources
  • Comment utiliser jq pour analyser des données au format json
  • Comment combiner des filtres à l’aide de « , » et « | »
  • Comment utiliser les fonctions length, keys, has et map
sudo apt install jq

Si nous avons une préférence pour la famille de distributions Red Hat, telles que Fedora, CentOS ou RHEL, nous pouvons installer jq via le gestionnaire de paquets dnf (dans les versions récentes de ces distributions, il a remplacé yum). Pour installer le paquet, nous exécuterions :

sudo dnf install jq

L’installation de jq sur Archlinux est tout aussi simple. Le gestionnaire de paquets de distribution est pacman, et le paquet est disponible dans le dépôt de la communauté. Nous pouvons effectuer l’installation avec la commande suivante :

sudo pacman -S install jq

Si nous ne pouvons pas, ou si pour une raison quelconque nous ne voulons pas utiliser un paquet binaire pré-construit, nous pouvons compiler jq à partir des sources. Dans
les lignes suivantes, nous décrivons les étapes nécessaires.

Construire et installer à partir des sources

Pour compiler et installer jq à partir des sources, la première chose que nous devons faire est de télécharger une archive de version. Au moment de la rédaction de
, la dernière version disponible est la 1.6. Pour télécharger l’archive tar sans quitter le terminal, nous pouvons utiliser wget :

wget https://github.com/stedolan/jq/releases/download/jq-1.6/jq-1.6.tar.gz

Une fois le téléchargement terminé, il faut décompresser et extraire l’archive :

tar -xzf jq-1.6.tar.gz

L’étape suivante consiste à entrer dans le répertoire jq-1.6, créé à la suite de la dernière commande :

cd jq-1.6

Maintenant, pour compiler le code source, nous avons besoin des utilitaires suivants :

  • gcc
  • Marque automatique
  • libtool
  • faire

Pour construire le logiciel que nous exécutons :

autoreconf -fi
./configure && make && sudo make install

Par défaut, la commande make install entraîne l’installation des fichiers binaires dans le répertoire /usr/local/bin et des bibliothèques dans /usr/local/lib. Si nous voulons personnaliser l’installation et modifier ces répertoires, nous devons spécifier un préfixe différent, en utilisant l’option --prefix lors du lancement du script ./configure.

Par exemple, pour installer le logiciel uniquement pour un utilisateur spécifique, nous pourrions passer le répertoire $HOME/.local comme préfixe : dans ce cas, les binaires seraient installés dans $HOME/.local/bin et les bibliothèques dans le $HOME/.local/lib ; Avec une telle configuration, il n’est pas nécessaire de lancer la commande make install avec des privilèges d’administration. Si vous voulez savoir comment mieux organiser les logiciels installés à partir du source, vous pouvez consulter notre article sur l’utilitaire de rangement GNU.

Utilisation

Une fois que jq est installé, nous pouvons l’utiliser pour analyser les fichiers json à partir de la ligne de commande. Pour les besoins de ce tutoriel, nous allons travailler avec une structure de données simple qui contient quelques détails sur trois personnages du livre Le Seigneur des Anneaux. Les données sont enregistrées dans le fichier characters.json.

L’utilitaire jq fonctionne en appliquant des filtres sur un flux de données json. Tout d’abord, nous utiliserons le filtre le plus simple, ., qui renvoie les données d’entrée inchangées mais assez imprimées. Pour cette caractéristique, il peut être utilisé pour formater les données de manière plus lisible :

jq . characters.json

La commande ci-dessus produit le résultat suivant :

{
  "characters": [
    {
      "name": "Aragorn",
      "race": "man"
    },
    {
      "name": "Gimli",
      "race": "dwarf"
    },
    {
      "name": "Legolas",
      "race": "elf"
    }
  ]
}

Maintenant, supposons que nous voulions filtrer les données pour n’obtenir que la valeur associée à la clé de caractères. Pour accomplir cette tâche, nous fournissons le nom de la clé et obtenons sa valeur (ou null si elle n’existe pas) :

jq .characters characters.json

Dans notre exemple, la valeur associée à la clé « characters » est un tableau, nous obtenons donc le résultat suivant :

[
  {
    "name": "Aragorn",
    "race": "man"
  },
  {
    "name": "Gimli",
    "race": "dwarf"
  },
  {
    "name": "Legolas",
    "race": "elf"
  }
]

Que se passe-t-il si nous voulons obtenir uniquement le premier élément du tableau ? Il suffit d’en « extraire » le bon indice. Sachant que les tableaux sont à base zéro, nous pouvons exécuter :

jq .characters[0] characters.json

La commande nous donne :

{
  "name": "Aragorn",
  "race": "man"
}

Nous pouvons également obtenir une tranche du tableau. Disons, par exemple, que nous voulons obtenir uniquement ses deux premiers éléments. Nous gérons :

jq .characters[0:2] characters.json

La commande nous donne le résultat suivant :

[
  {
    "name": "Aragorn",
    "race": "man"
  },
  {
    "name": "Gimli",
    "race": "dwarf"
  }
]

Le découpage fonctionne également sur les cordes, donc si nous exécutons :

jq .characters[0].name[0:2] characters.json

On obtient une tranche (les deux premières lettres) de la chaîne « Aragorn » : « Ar ».

Accéder aux éléments du réseau séparément

Dans les exemples ci-dessus, nous avons imprimé le contenu du tableau « characters », qui se compose de trois objets qui décrivent des personnages fantastiques. Que se passe-t-il si nous voulons itérer sur ledit tableau ? Nous devons faire en sorte que les éléments qu’il contient soient renvoyés séparément, nous devons donc utiliser [] sans fournir d’index :

jq .characters[] characters.json

Le résultat de la commande est le suivant :

{
  "name": "Aragorn",
  "race": "man"
}
{
  "name": "Gimli",
  "race": "dwarf",
  "weapon": "axe"
}
{
  "name": "Legolas",
  "race": "elf"
}

Dans ce cas, nous avons obtenu 3 résultats : les objets contenus dans le tableau. La même technique peut être utilisée pour itérer sur les valeurs d’un objet, dans ce cas la première contenue dans le tableau « characters » :

jq .characters[0][] characters.json

Ici, nous obtenons le résultat suivant :

"Aragorn"
"man"

Les opérateurs « , » et « | »

Les opérateurs « » et « | » sont tous deux utilisés pour combiner deux filtres ou plus, mais ils fonctionnent de différentes manières. Lorsque deux filtres sont séparés par une virgule, ils sont tous deux appliqués, séparément, sur les données données données et nous permettent d’obtenir deux résultats différents. Voyons un exemple :

jq '.characters[0], .characters[2]' characters.json

Les données au format json contenues dans le fichier characters.json sont d’abord filtrées avec .characters[0] puis avec .charaters[2], pour obtenir le premier et le troisième élément du tableau « characters ». En exécutant la commande ci-dessus, nous obtenons deux résultats distincts :

{
  "name": "Aragorn",
  "race": "man"
}
{
  "name": "Legolas",
  "race": "elf"
}

L’opérateur « | » fonctionne différemment, de la même manière qu’un tube unix. La sortie produite par le filtre à gauche de l’opérateur, est transmise en entrée au filtre à droite de l’opérateur. Si un filtre à gauche de l’opérateur produit plusieurs résultats, le filtre à droite de l’opérateur est appliqué à chacun d’entre eux :

jq '.characters[] | .name' characters.json

Dans cet exemple, nous avons deux filtres. À gauche de l’opérateur, nous avons le filtre .characters[], qui, comme nous l’avons vu précédemment, nous permet d’obtenir les éléments du tableau « characters » comme résultats séparés. Dans notre cas, chaque résultat est un objet avec les propriétés « name » et « race ». Le filtre .name à droite de l’opérateur | est appliqué à chacun des objets, nous obtenons donc le résultat suivant :

"Aragorn"
"Gimli"
"Legolas"

Fonctions

L’utilitaire jq comprend des fonctions très utiles que nous pouvons appliquer aux données formatées json. Nous allons maintenant en voir quelques-uns : longueur, clés, has et map.

La fonction length

Le premier dont nous parlerons est la longueur, qui, comme son nom l’indique, nous permet de récupérer la longueur d’objets, de tableaux et de chaînes. La longueur des objets est le nombre de leurs paires clé-valeur ; La longueur des tableaux est représentée par le nombre d’éléments qu’ils contiennent ; La longueur d’une chaîne est le nombre de caractères qui la composent. Voyons comment utiliser la fonction. Supposons que nous voulions connaître la longueur du tableau « characters », nous exécutons :

jq '.characters | length' characters.json

Comme prévu, nous obtenons 3 comme résultat, puisqu’il s’agit du nombre d’éléments dans le tableau. De la même manière, pour obtenir la longueur du premier objet du tableau, nous pourrions exécuter :

jq '.characters[0] | length' characters.json

Cette fois, nous obtenons 2 comme résultat, puisqu’il s’agit du nombre de paires de valeurs contenues dans l’objet. Comme nous l’avons déjà dit, la même fonction appliquée à une chaîne de caractères, renvoie le nombre de caractères qu’elle contient, donc, par exemple, en exécutant :

jq '.characters[0].name | length' characters.json

Nous obtenons 7 comme résultat, ce qui est la longueur de la chaîne « Aragorn ».

La fonction des touches

La fonction keys peut être appliquée sur des objets ou des tableaux. Dans le premier cas, il renvoie un tableau contenant
les clés des objets :

jq '.characters[0] | keys' characters.json
[
  "name",
  "race"
]

Lorsqu’il est appliqué à un tableau, il renvoie un autre tableau contenant les indices du premier :

jq '.characters | keys' characters.json
[
  0,
  1,
  2
]

La fonction keys renvoie les éléments triés : si nous voulons que les éléments soient renvoyés dans l’ordre d’insertion, nous pouvons utiliser la fonction keys_unsorted à la place.

Vérifier si un objet possède une clé

Une opération très courante que nous pouvons vouloir effectuer sur un objet consiste à vérifier s’il contient une clé spécifique. Pour accomplir cette tâche, nous pouvons utiliser la fonction has. Par exemple, pour vérifier si l’objet principal de nos données au format json contient la clé « weapons », nous pourrions exécuter :

jq 'has("weapons")' characters.json
false

Dans ce cas, comme prévu, la fonction a renvoyé false puisque l’objet ne contient que la clé « characters » :

jq 'has("characters")' characters.json
true

Lorsqu’elle est appliquée à des tableaux, la fonction renvoie true si le tableau a un élément à l’index donné ou false dans le cas contraire :

jq '.characters | has(3)' characters.json
false

Le tableau « caractères » n’a que 3 éléments ; Les tableaux sont indexés par zéro, donc vérifier si le tableau en tant qu’élément associé à l’indice 3 renvoie false.

La fonction de carte

La fonction map nous permet d’appliquer un filtre à chaque élément d’un tableau donné. Par exemple, supposons que nous voulions vérifier l’existence de la clé « name » dans chacun des objets contenus dans le tableau « characters ». Nous pouvons combiner la carte et avons des fonctions de cette façon :

jq '.characters | map(has("name"))' characters.json
[
  true,
  true,
  true
]

Conclusions

Dans cet article, nous ne faisons qu’effleurer la surface des fonctionnalités offertes par l’utilitaire jq qui nous permet d’analyser et de manipuler des données au format json à partir de la ligne de commande. Nous avons appris l’utilisation de base du programme, comment fonctionnent les opérateurs « , » et « | », et comment utiliser les fonctions length, keys, has et map, pour obtenir respectivement les longueurs des tableaux, des chaînes de caractères et des objets, obtenir des clés d’objet ou des index de tableau, vérifier si une clé existe dans un objet ou si un tableau a un élément à l’index donné, et appliquer un filtre ou une fonction à chaque élément d’un tableau. Pour découvrir tout ce que jq peut faire, allez jeter un coup d’œil au manuel du programme !

Articles connexes: