Passer la variable bash à jq


113

J'ai écrit un script pour récupérer une certaine valeur file.json. Cela fonctionne si je donne la valeur à jq select, mais la variable ne semble pas fonctionner (ou je ne sais pas comment l'utiliser).

#!/bin/sh

#this works ***
projectID=$(cat file.json | jq -r '.resource[] | select(.username=="myemail@hotmail.com") | .id')
echo "$projectID"

EMAILID=myemail@hotmail.com

#this does not work *** no value is printed
projectID=$(cat file.json | jq -r '.resource[] | select(.username=="$EMAILID") | .id')
echo "$projectID"

Un problème connexe: le passage de la variable bash au filtre jq a la syntaxe légèrement différente jq -r --arg var "$var" '.[$var]' stackoverflow.com/questions/34745451/...
enharmonic

Réponses:


177

Envisagez également de passer la variable shell (EMAILID) en tant que variable jq (ici aussi EMAILID, à titre d'illustration):

   projectID=$(cat file.json | 
     jq -r --arg EMAILID "$EMAILID" '
        .resource[]
        | select(.username==$EMAILID) 
        | .id')

Postscript

Pour mémoire, une autre possibilité serait d'utiliser la envfonction de jq pour accéder aux variables d'environnement. Par exemple, considérez cette séquence de commandes bash:

EMAILID=foo@bar.com  # not exported
EMAILID="$EMAILID" jq -n 'env.EMAILID'

La sortie est une chaîne JSON:

"foo@bar.com"

4
C'est la seule réponse sûre à 100%; il permet de jqcréer correctement le filtre en utilisant la valeur, plutôt que d'utiliser bashpour créer une chaîne qui jqinterprète comme un filtre. (Considérez ce qui se passe si la valeur de EMAILIDcontient a ).)
chepner

3
Merci pic. votre solution fournie est la bonne réponse que je recherchais. Oui cela fonctionne.
asidd

Mon cas d'utilisation, ça marche! function n2 { termux-contact-list |jq -r --arg v1 "$1" '.[] | select(.name==$v1)|.number' }Appel:n2 Name1
Timo

2
fyi, la envfonction de jq est modifiée entre jq 1.4 et 1.5+, donc les références à env.EMAILID(dans l'exemple de cette réponse) ne fonctionnent pas dans jq 1.4, recommandant ainsi d'utiliser la --arg EMAILID "$EMAILID"construction si vous devez utiliser jq 1.4. J'espère que cela t'aides; m'a juste pris un jour + pour comprendre cela par moi-même;)
m0j0hn

3
Les arguments passés en utilisant --argseront passés sous forme de chaînes. Si vous souhaitez transmettre des données d'un type JSON différent, utilisez --argjson, qui analysera la chaîne en tant que JSON, par exemple--argjson myObj '{"a": [1, 2]}'
BallpointBen

25

J'ai résolu ce problème en échappant les guillemets doubles internes

projectID=$(cat file.json | jq -r ".resource[] | select(.username==\"$EMAILID\") | .id")

J'utilise ceci parce que --arg ne joue pas bien avec-c
Dimitris Moraitidis

9

C'est un problème de devis, vous avez besoin de:

projectID=$(
  cat file.json | jq -r ".resource[] | select(.username=='$EMAILID') | .id"
)

Si vous mettez des guillemets simples pour délimiter la chaîne principale, le shell prend $EMAILIDlittéralement.

« Guillemets » chaque littéral qui contient des espaces / métacaractères et chaque extension: "$var", "$(command "$var")", "${array[@]}", "a & b". Utilisez 'single quotes'pour le code ou littéral $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. Voir
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words


Dans mon erreur de cas aussi bien, sinon similaire en utilisant des citations du tout: termux-contact-list |jq -r '.[] | select(.name=='$1')|.number'. Résultat:jq Compile error
Timo

6
Je ne sais pas pourquoi ce commentaire a été voté autant de fois; oui, les guillemets doubles permettent l'expansion des variables, mais jqjq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?)
n'aiment

Si votre entrée est un json normal, alors ses valeurs seraient doubles (pas simples) entre guillemets. Ce qui fonctionne: Utiliser des guillemets doubles pour tout l'argument de jq et échapper (avec `\`) tous les guillemets doubles à l'intérieur, comme @asid a répondu.
GuSuku

6

Publiez-le ici car cela pourrait aider les autres. Dans la chaîne, il peut être nécessaire de passer les guillemets à jq. Pour faire ce qui suit avec jq:

.items[] | select(.name=="string")

en bash tu pourrais faire

EMAILID=$1
projectID=$(cat file.json | jq -r '.resource[] | select(.username=='\"$EMAILID\"') | .id')

échapper essentiellement les guillemets et les transmettre à jq


Fonctionne parfaitement. Pas trop compliqué pour quelqu'un qui cherche une solution rapide.
Mo-Gang le

4

Une autre façon d'accomplir cela est d'utiliser l'indicateur jq "--arg". En utilisant l'exemple d'origine:

#!/bin/sh

#this works ***
projectID=$(cat file.json | jq -r '.resource[] | 
select(.username=="myemail@hotmail.com") | .id')
echo "$projectID"

EMAILID=myemail@hotmail.com

# Use --arg to pass the variable to jq. This should work:
projectID=$(cat file.json | jq --arg EMAILID $EMAILID -r '.resource[] 
| select(.username=="$EMAILID") | .id')
echo "$projectID"

Voir ici, où j'ai trouvé cette solution: https://github.com/stedolan/jq/issues/626


2

Je sais que c'est un peu plus tard pour répondre, désolé. Mais cela fonctionne pour moi.

export K8S_public_load_balancer_url="$(kubectl get services -n ${TENANT}-production -o wide | grep "ingress-nginx-internal$" | awk '{print $4}')"

Et maintenant, je suis capable de récupérer et de transmettre le contenu de la variable à jq

export TF_VAR_public_load_balancer_url="$(aws elbv2 describe-load-balancers --region eu-west-1 | jq -r '.LoadBalancers[] | select (.DNSName == "'$K8S_public_load_balancer_url'") | .LoadBalancerArn')"

Dans mon cas, j'avais besoin d'utiliser des guillemets doubles et des guillemets pour accéder à la valeur de la variable.

À votre santé.


1

Jq a maintenant un meilleur moyen d'accéder aux variables d'environnement, vous pouvez utiliser env.EMAILI:

projectID=$(cat file.json | jq -r ".resource[] | select(.username==env.EMAILID) | .id")

0

Peu sans rapport mais je vais quand même le mettre ici, Pour d'autres raisons pratiques, les variables shell peuvent être utilisées comme -

value=10
jq  '."key" = "'"$value"'"' file.json
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.