URL: https://linuxfr.org/users/bfg/journaux/json-en-ligne-de-commande-jq-pjy Title: JSON en ligne de commande : jq/pjy Authors: BFG Date: 2018年02月20日T09:17:03+01:00 License: CC By-SA Tags: json, cli, shell et ligne_de_commande Score: 22 Salut à toi, Nal, Connais tu `jq` ? C'est un outil en ligne de commande bien pratique quand on a des données en JSON et qu'on veut en extraire quelques infos. On lui passe un fichier JSON, une expression bien sentie dans un langage spécifique et concis, et le tour est joué. Alors, je sais pas pour toi, Nal, mais je galère quand même pas mal chaque fois pour réussir à écrire l'expression qui va bien, car `jq` a son langage à lui, et il n'est pas des plus simples. Je trouve que ça devient assez compliqué dès qu'il s'agit de faire une boucle qui fait un peu plus que retourner un champ d'un dictionnaire. Ça serait quand même plus pratique si la syntaxe était celle d'un langage que je maitrise déjà, par exemple Python. Bon, à ce stade là de mon approche pas très discrète, tu dois te douter que je vais tenter de te vendre ma came. Alors allons-y : j'ai écrit `pjy`, un outil comme `jq`, mais qui utilise la syntaxe de Python. Si tu connais Python, tu sais (presque) déjà utiliser `pjy`. ``` pjy 'data["toto"] + 1' fichier.json ``` Comme pour `jq`, on passe d'abord l'expression à évaluer (en Python cette fois), et le fichier JSON. `data` représente le fichier JSON. Ici, le fichier JSON était un dictionnaire avec une clef `toto`, et j'affiche la valeur associée à cette clef, plus un. Simple. Malgré sa syntaxe facétieuse, il faut bien avouer que la notation de `jq` `x.y` au lieu de `x["y"]` est pratique. Je l'ai donc emprunté (et ajouté un alias "d" pour "data") : ``` pjy 'd.toto + 1' fichier.json ``` À ce moment là, j'étais déjà content du résultat, débarrassé de `jq`, je pouvais enfin écrire une double boucle sans m'arracher les cheveux : ``` [[s[:i] for i in range(len(s))] for s in d.chaines] ``` Mais je me suis dit que `jq` avait quelques petits trucs sympas, que je pouvais également emprunter, de manière optionnelle bien entendue, pour qu'on puisse toujours revenir à une syntaxe Python, standard et lisible, qui est la raison d'être de `pjy`. J'ai donc emprunté à `jq` la barre verticale pour réaliser la fonction `map`, on peut ainsi remplacer : ``` map(lambda x: x + 1, data["nombres"]) ``` Par : ``` data["nombres"] | lambda x: x + 1 ``` Si tu as tout suivi, tu noteras que l'on peut également écrire : ``` d.nombres | lambda x: x + 1 ``` J'avais repéré depuis pas mal de temps le paquet [`placeholder`](https://pypi.python.org/pypi/placeholder/), qui permet d'écrire des lambdas basiques de manière assez concise. Je l'ai ré-implémenté et rajouté la variable `_` qui une fonction spéciale, au début la fonction identité, mais qui absorbe toutes les opérations pour les ré-appliquer plus tard. En reprenant l'exemple précédent, ça donne : ``` d.nombres | _ + 1 ``` Il y a quelques petites fonctionnalités en plus (comme plusieurs fichiers en entrée), que tu pourras découvrir. Si tu es curieux ou convaincu, je t'invite à tester : https://pypi.python.org/pypi/pjy ``` pip3 install pjy ``` C'est du Python 3, pas de Python 2, et pas de dépendances externes (`pygments` est optionnel, pour la coloration). C'est sous licence WTFPL. À noter ce paquet qu'il peut être intéressant d'utiliser dans `pjy` : http://0101.github.io/pipetools/doc/ Que penses-tu de tout ça, Nal ?