Übergabe der Bash-Variablen an jq select

111

Ich habe ein Skript geschrieben, um einen bestimmten Wert abzurufen file.json. Es funktioniert, wenn ich den Wert für jq gebe select, aber die Variable scheint nicht zu funktionieren (oder ich weiß nicht, wie ich sie verwenden soll).

#!/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
quelle
Ein verwandtes Problem: Die Übergabe der Bash-Variablen an den JQ-Filter hat eine etwas andere Syntax. jq -r --arg var "$var" '.[$var]' Stackoverflow.com/questions/34745451/…
Enharmonic

Antworten:

172

Überlegen Sie auch, ob Sie die Shell-Variable (EMAILID) als jq-Variable übergeben möchten (hier zur Veranschaulichung auch EMAILID):

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

Nachtrag

Für den Datensatz besteht eine andere Möglichkeit darin, die envFunktion von jq für den Zugriff auf Umgebungsvariablen zu verwenden. Betrachten Sie beispielsweise diese Folge von Bash-Befehlen:

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

Die Ausgabe ist eine JSON-Zeichenfolge:

"[email protected]"
Gipfel
quelle
4
Dies ist die einzige 100% sichere Antwort. Damit können Sie jqden Filter ordnungsgemäß mit dem Wert erstellen, anstatt basheine Zeichenfolge zu erstellen, jqdie als Filter interpretiert wird. (Überlegen Sie, was passiert, wenn der Wert von a EMAILIDenthält ).)
chepner
3
Danke Peak. Ihre bereitgestellte Lösung ist die richtige Antwort, nach der ich gesucht habe. Ja es funktioniert.
Asidd
Mein Anwendungsfall, es funktioniert! function n2 { termux-contact-list |jq -r --arg v1 "$1" '.[] | select(.name==$v1)|.number' }Aufruf:n2 Name1
Timo
2
Zu Ihrer Information, die envFunktion von jq wird zwischen jq 1.4 und 1.5+ geändert, sodass Verweise auf env.EMAILID(im Beispiel dieser Antwort) in jq 1.4 nicht funktionieren. Daher wird empfohlen, das --arg EMAILID "$EMAILID"Konstrukt zu verwenden, wenn Sie jq 1.4 verwenden müssen. Hoffe das hilft; Ich habe nur einen Tag
gebraucht
3
Mit übergebene Argumente --argwerden als Zeichenfolgen übergeben. Wenn Sie Daten eines anderen JSON-Typs übergeben möchten, verwenden Sie --argjson, wodurch die Zeichenfolge als JSON analysiert wird, z. B.--argjson myObj '{"a": [1, 2]}'
BallpointBen,
25

Ich habe dieses Problem gelöst, indem ich mich den inneren doppelten Anführungszeichen entzogen habe

projectID=$(cat file.json | jq -r ".resource[] | select(.username==\"$EMAILID\") | .id")
asidd
quelle
Ich benutze dies, weil --arg nicht gut mit-c
Dimitris Moraitidis spielt
9

Es ist ein Zitat, das Sie brauchen:

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

Wenn Sie einfache Anführungszeichen setzen , um die Hauptzeichenfolge abzugrenzen, wird die Shell $EMAILIDwörtlich genommen.

„Double - Zitat“ jeder wörtlich , die Leerzeichen / Metazeichen und enthält jede Expansion: "$var", "$(command "$var")", "${array[@]}", "a & b". Verwendung 'single quotes'für Code oder Literal $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. Siehe
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words

Gilles Quenot
quelle
Auch in meinem Fall Fehler, ähnlich, wenn überhaupt keine Anführungszeichen verwendet werden : termux-contact-list |jq -r '.[] | select(.name=='$1')|.number'. Ergebnis:jq Compile error
Timo
6
Ich bin mir nicht sicher, warum dieser Kommentar so oft gewählt wurde. Ja, doppelte Anführungszeichen ermöglichen eine variable Erweiterung, jqmögen aber keine einfachen Anführungszeichen:jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?)
jdelman
Wenn Ihre Eingabe ein regulärer json ist, werden seine Werte in doppelte (nicht einfache) Anführungszeichen gesetzt. Was funktioniert: Verwenden Sie doppelte Anführungszeichen für das gesamte Argument von jq und maskieren Sie (mit `\`) alle doppelten Anführungszeichen, wie @asid geantwortet hat.
GuSuku
5

Poste es hier, da es anderen helfen könnte. In einer Zeichenfolge kann es erforderlich sein, die Anführungszeichen an jq zu übergeben. Gehen Sie mit jq wie folgt vor:

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

in bash könnte man machen

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

im Wesentlichen den Anführungszeichen entkommen und an jq weitergeben

Zaid
quelle
Funktioniert perfekt. Nicht zu kompliziert für jemanden, der nach einer schnellen Lösung sucht.
Mo-Gang
4

Eine andere Möglichkeit, dies zu erreichen, ist das jq-Flag "--arg". Verwenden Sie das ursprüngliche Beispiel:

#!/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"

Hier habe ich diese Lösung gefunden: https://github.com/stedolan/jq/issues/626

Andrew Lockhart
quelle
2

Ich weiß, es ist etwas später zu antworten, sorry. Aber das funktioniert bei mir.

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

Und jetzt kann ich den Inhalt der Variablen abrufen und an jq übergeben

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')"

In meinem Fall musste ich doppelte Anführungszeichen und Anführungszeichen verwenden, um auf den Variablenwert zuzugreifen.

Prost.

Rodrigo Andrade
quelle
1

Jq hat jetzt eine bessere Möglichkeit, auf Umgebungsvariablen zuzugreifen. Sie können env.EMAILI verwenden:

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

Wenig unabhängig, aber ich werde es trotzdem hier setzen. Für andere praktische Zwecke können Shell-Variablen verwendet werden als -

value=10
jq  '."key" = "'"$value"'"' file.json
Markroxor
quelle