3
votes

jq lit une chaîne en ligne, pas depuis stdin

Cela peut lire à partir d'un fichier:

jq '.field' "$my_json"

cela lit à partir de stdin:

echo "$my_json" | jq -r '.field'

que faire si je veux juste lire à partir d'un chaîne comme ceci:

jq '.c | fromjson | .id' my_file.json

comment faire cela?


0 commentaires

4 Réponses :


1
votes

Vous pouvez utiliser une fonctionnalité bash qui vous permet de rediriger stdin à partir d'une chaîne littérale avec l'opérateur :

$ jq .field <<< '{"field": 3}'
3

Il fonctionne bien sûr également avec JSON en ligne:

$ json='{"field": 3}'
$ jq .field <<< "$json"
3


3 commentaires

quelque chose comme ça serait bien jq '.field' -s "$ my_json_string"


Actuellement, jq n'a pas une telle fonctionnalité. Ce pourrait être une décision de conception intentionnelle; selon la philosophie UNIX selon laquelle «tout est un fichier», il pourrait être plus simple qu'un programme n'accepte que les entrées sur stdin et laisse le shell gérer la redirection, au lieu de dans chaque programme implémentant toutes les fonctionnalités que les utilisateurs peuvent souhaiter lire depuis le clavier, lire depuis le socket, lire depuis une chaîne littérale, ...)


tout n'est pas un fichier mais tout est un flux de caractères imo, et une chaîne arg est juste cela. néanmoins, MrCholo approuve cette réponse.



2
votes
$ jq -n '$in.foo' --argjson in '{"foo":"bar"}'
"bar"
$ jq -n '$foo' --arg foo 'bar'
"bar"

-n to use null as input (instead of STDIN),
--argjson for passing a JSON entity (object, array, number, string, boolean or null)
--arg for passing a (shell) string.

3 commentaires

voté ... mais semble être des arguments cli compliqués - je n'aurai aucune idée de ce qu'il fait si je le regarde dans un an, y a-t-il une API plus simple pour cela?


@OguzIsmail - En général, je pense qu'il vaut mieux utiliser la commande COMMAND OPTIONS ARGS. Aviez-vous une raison particulière de faire autrement?


dans le second pourquoi est-ce jq -n '$ foo' --arg foo 'bar' pourquoi avez-vous besoin du 'bar' à la fin? Je m'attendrais à ce que cela suffise: jq -n '$ foo' --arg '.foo'



0
votes

Une troisième possibilité est de lire une chaîne à partir de l'environnement:

$ jq -n '$ARGS.positional[0]|fromjson.field' --args '{"field": 333}'
333

La quatrième possibilité (et essentiellement la seule autre) est d'utiliser des arguments de position (jq 1.5 et supérieur): p >

$ string='{"field": 33}' jq -n '$ENV.string|fromjson.field'
33


2 commentaires

assez bizarre, pourquoi ne pas simplement lire les variables d'environnement avec le standard $ xyz (ne pas vous blâmer, juste l'auteur de la bibliothèque). Consultez cette réponse ici stackoverflow.com/a/57043296/5047085


L'utilisation de l'interpolation de chaîne du shell n'a rien à voir avec jq ou ses auteurs. Il y a des occasions où cette technique a du sens, mais elle peut entraîner confusion et complications, et pas seulement pour les utilisateurs de Windows. L'une des nombreuses sources de complications potentielles est que jq a ses propres variables "$".



-3
votes

Un simple appel utilisant -n devrait suffire:

> jq -nr '{foo: "bar",baz: "test"}|.foo'
bar

exemple:

jq -nr "${my_json}|.field"


5 commentaires

gentil, je pourrais sélectionner ceci comme réponse - pouvez-vous créer un lien vers les documents où cela est documenté?


Cette réponse utilise l'interpolation de chaîne du shell, qui n'a rien à voir avec jq. Il y a des occasions où cette technique a du sens, mais cela dépend du shell que vous utilisez. En règle générale, en particulier sur un site Web général de questions-réponses, les alternatives les plus robustes doivent être préférées.


@MrCholo ne sait pas quelle partie ne vous semble pas claire. -n fait que jq ne lit aucune entrée, traite simplement son argument. Et sur la ligne de commande, vous définissez simplement l'objet json et le «dirigez» vers le sélecteur «.field» qui sélectionne ce champ.


@peak Je ne vois pas comment cette réponse utilise uniquement l'interpolation shell str, elle utilise clairement JQ


@MrCholo - Je n'ai pas dit que la réponse dans son ensemble n'utilise pas jq. J'ai dit que la réponse utilise (c'est-à-dire qu'elle repose sur) l'interpolation shell. Vous devriez lire sur le shell. Ou placez le filtre dans un fichier, par exemple filter.jq, puis exécutez jq -nr -f filter.jq