jq selectにbash変数を渡す


112

から特定の値を取得するスクリプトを作成しましたfile.json。jq selectに値を指定すると機能しますが、変数が機能しないようです(または使用方法がわかりません)。

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

関連する問題:JQフィルターにbashの変数を渡すには、わずかに異なる構文があるjq -r --arg var "$var" '.[$var]' stackoverflow.com/questions/34745451/...
異名同音

回答:


176

シェル変数(EMAILID)をjq変数として渡すことも検討してください(ここでは、説明のためにEMAILIDも使用しています)。

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

追記

記録として、もう1つの可能性は、jqのenv関数を使用して環境変数にアクセスすることです。たとえば、次のbashコマンドのシーケンスを考えてみます。

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

出力はJSON文字列です。

"foo@bar.com"

4
これが唯一の100%安全な答えです。jqフィルターとして解釈bashする文字列を作成するのではなく、値を使用してフィルターを適切に作成できますjq。(の値にがEMAILID含まれているとどうなるかを検討してください)。)
chepner

3
ピークありがとう。あなたの提供した解決策は私が探していた適切な対応です。はい、動作します。
2016年

私のユースケース、それはうまくいきます!function n2 { termux-contact-list |jq -r --arg v1 "$1" '.[] | select(.name==$v1)|.number' }コーリング:n2 Name1
Timo

2
fyi、jqのenv関数はjq 1.4と1.5+の間で変更されているため、env.EMAILID(この回答の例では)への参照はjq 1.4では機能しないため、jq 1.4 --arg EMAILID "$EMAILID"を使用する必要がある場合は構成を使用することをお勧めします。お役に立てれば; 自分でこれを理解するのに1日以上かかりました;)
m0j0hn 2018年

3
を使用して--arg渡される引数は、文字列として渡されます。別のJSONタイプのデータを渡す場合は、を使用します--argjson。これにより、文字列をJSONとして解析します。例:--argjson myObj '{"a": [1, 2]}'
BallpointBen

25

内側の二重引用符をエスケープしてこの問題を解決しました

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

--argがうまく機能しないため、これを使用しています-c
Dimitris Moraitidis

9

それは引用問題です、あなたは必要です:

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

メイン文字列を区切るために一重引用符を入れると、シェルは$EMAILID文字通り解釈します。

「二重引用符」スペース/メタ文字を含むすべてのリテラルと、すべての拡張:"$var""$(command "$var")""${array[@]}""a & b"。使用する'single quotes'コードまたはリテラルのために$'s: 'Costs $5 US'ssh host 'echo "$HOSTNAME"'。参照してください
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words


私の場合も同様に、引用符をまったく使用しない場合でも同様ですtermux-contact-list |jq -r '.[] | select(.name=='$1')|.number'。結果:jq Compile error
ティモ

6
このコメントが何度も投票された理由がわかりません。はい、二重引用符は変数の拡張を可能にしますが、jq単一引用符は好きではありません:jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?)
jdelman

入力が通常のjsonの場合、その値は二重(単一ではなく)で引用されます。機能:jqの引数全体に二重引用符を使用し、@ asidが回答したように、二重引用符を( `\`で)エスケープします。
GuSuku

5

他の人の役に立つかもしれないので、ここに投稿してください。文字列では、引用符をjqに渡す必要がある場合があります。jqで以下を実行するには:

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

バッシュであなたはできる

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

基本的に引用符をエスケープしてjqに渡す


完璧に動作します。簡単な解決策を探している人にとってはそれほど複雑ではありません。
Mo-Gang

4

これを行う別の方法は、jq "--arg"フラグを使用することです。元の例を使用:

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

私がこのソリューションを見つけたここを参照してください:https : //github.com/stedolan/jq/issues/626


2

すみません、後で返信します。しかし、それでうまくいきます。

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

そして今、私は変数の内容をフェッチして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')"

私の場合、変数値にアクセスするには二重引用符と引用符を使用する必要がありました。

乾杯。


1

Jqに環境変数にアクセスするためのより良い方法が用意されました。env.EMAILIを使用できます。

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

0

ほとんど関係ありませんが、ここではここに置きます。他の実用的な目的では、シェル変数を-として使用できます。

value=10
jq  '."key" = "'"$value"'"' file.json
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.