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=="[email protected]") | .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"
asidd
la source
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:

"[email protected]"
de pointe
la source
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")
asidd
la source
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

Gilles Quenot
la source
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

Zaid
la source
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=="[email protected]") | .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

Andrew Lockhart
la source
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é.

Rodrigo Andrade
la source
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")
DukeLion
la source
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
Markroxor
la source