Bash değişkenini jq'ye geçirme


114

Belirli bir değeri almak için bir komut dosyası yazdım file.json. Jq değerini sağlarsam işe yarar select, ancak değişken çalışmıyor (veya nasıl kullanacağımı bilmiyorum).

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

İlgili bir sorun: bash değişkenini jq filtresine geçirmek biraz farklı sözdizimine sahip jq -r --arg var "$var" '.[$var]' stackoverflow.com/questions/34745451/…
Enharmonic

Yanıtlar:


182

Kabuk değişkenini (EMAILID) bir jq değişkeni olarak (burada ayrıca örnekleme amacıyla EMAILID) geçirmeyi düşünün:

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

Postscript

Kayıt için başka bir olasılık, envortam değişkenlerine erişmek için jq'nin işlevini kullanmak olabilir . Örneğin, şu bash komutları dizisini düşünün:

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

Çıktı bir JSON dizesidir:

"foo@bar.com"

4
Bu% 100 güvenli tek cevaptır; jqfiltre olarak yorumlayan bashbir dize oluşturmak yerine değeri kullanarak filtreyi düzgün bir şekilde oluşturmanıza izin verir jq. (Değeri EMAILIDa içeriyorsa ne olacağını düşünün ).)
chepner

3
Teşekkürler zirve. Sağladığınız çözüm, aradığım doğru yanıttı. Evet çalışıyor.
asidd

Benim kullanım durumum işe yarıyor! function n2 { termux-contact-list |jq -r --arg v1 "$1" '.[] | select(.name==$v1)|.number' }Aranıyor:n2 Name1
Timo

2
fyi, jq'nin envişlevi jq 1.4 ve 1.5+ arasında değiştirilir, bu nedenle env.EMAILID(bu yanıt örneğinde) jq 1.4'te çalışmaz, bu nedenle --arg EMAILID "$EMAILID"jq 1.4 kullanmanız gerekiyorsa yapıyı kullanmanızı öneririm . Bu yardımcı olur umarım; bunu kendim çözmem için bir günümü aldı;)
m0j0hn

3
Kullanılarak geçirilen bağımsız değişkenler --argdizeler olarak aktarılacaktır. Farklı bir JSON türündeki verileri iletmek istiyorsanız --argjson, dizeyi JSON olarak ayrıştıracak olan kullanın , örneğin,--argjson myObj '{"a": [1, 2]}'
BallpointBen

26

Bu sorunu, içteki çift tırnak işaretlerinden kaçarak çözdüm

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

Bunu kullanıyorum çünkü --arg ile iyi oynamıyor-c
Dimitris Moraitidis

9

Bu bir teklif sorunu, ihtiyacınız olan:

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

Ana dizeyi sınırlamak için tek tırnak işareti koyarsanız , kabuk $EMAILIDtam anlamıyla alır .

"Çift tırnak" boşluk / meta karakterler ve içeren her değişmezi her genişleme: "$var", "$(command "$var")", "${array[@]}", "a & b". Kullanın 'single quotes'kodu veya literal için $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. Bkz.
Http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words


Benim de vaka hatası olarak, eğer benzer hiç tırnak kullanmıyor: termux-contact-list |jq -r '.[] | select(.name=='$1')|.number'. Sonuç:jq Compile error
Timo

6
Bu yorumun neden bu kadar çok oylandığından emin değilim; evet, çift tırnak değişken genişletmeye izin verir, ancak jqtek tırnakları jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?)
sevmez

Girdiniz normal bir json ise, değerleri çift (tek değil) tırnaklı olacaktır. Ne işe yarıyor: jq'nin tüm argümanı için çift tırnak kullanmak ve @asid'in yanıtı gibi, içindeki herhangi bir çift tırnak işaretinden kaçmak (`\` ile).
GuSuku

6

Başkalarına yardımcı olabileceği için buraya göndermek. Dize olarak tırnakları jq'ye geçirmek gerekebilir. Jq ile aşağıdakileri yapmak için:

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

Bash'de yapabilirsin

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

esasen alıntılardan kaçıp jq'ye iletmek


Mükemmel çalışıyor. Hızlı bir çözüm arayan biri için çok karmaşık değil.
Mo-Gang

4

Bunu başarmanın bir başka yolu da jq "--arg" bayrağını kullanmaktır. Orijinal örneği kullanarak:

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

Buraya bakın, bu çözümü bulduğum yer: https://github.com/stedolan/jq/issues/626


2

Biliyorum biraz geç cevap vereceğim, üzgünüm. Ama bu benim için çalışıyor.

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

Ve şimdi değişkenin içeriğini alabiliyorum ve jq'ye geçirebiliyorum

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

Benim durumumda, değişken değere erişmek için çift tırnak ve tırnak kullanmam gerekiyordu.

Şerefe.


1

Jq artık ortam değişkenlerine erişmenin daha iyi bir yoluna sahip, env.EMAILI'yi kullanabilirsiniz:

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

0

Biraz ilgisiz ama yine de buraya koyacağım, Diğer pratik amaçlar için kabuk değişkenleri şu şekilde kullanılabilir -

value=10
jq  '."key" = "'"$value"'"' file.json
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.