将 bash 变量传递给 jq
Posted
技术标签:
【中文标题】将 bash 变量传递给 jq【英文标题】:Passing bash variable to jq 【发布时间】:2017-02-22 22:55:22 【问题描述】:我编写了一个脚本来从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 -r --arg var "$var" '.[$var]'
***.com/questions/34745451/…
【参考方案1】:
考虑也将 shell 变量 (EMAILID) 作为 jq 变量传递(这里也是 EMAILID,为了便于说明):
projectID=$(jq -r --arg EMAILID "$EMAILID" '
.resource[]
| select(.username==$EMAILID)
| .id' file.json)
后记
为了记录,另一种可能性是使用 jq 的env
函数来访问环境变量。例如,考虑以下 bash 命令序列:
EMAILID=foo@bar.com # not exported
EMAILID="$EMAILID" jq -n 'env.EMAILID'
输出是一个 JSON 字符串:
"foo@bar.com"
【讨论】:
这是唯一 100% 安全的答案;它让jq
使用该值正确创建过滤器,而不是使用bash
创建jq
解释为过滤器的字符串。 (考虑如果EMAILID
的值包含)
会发生什么。)
感谢高峰。您提供的解决方案是我正在寻找的正确响应。是的,它有效。
我的用例,它有效! function n2 termux-contact-list |jq -r --arg v1 "$1" '.[] | select(.name==$v1)|.number'
来电:n2 Name1
fyi,jq 的 env
函数在 jq 1.4 和 1.5+ 之间更改,因此对 env.EMAILID
的引用(在此答案的示例中)在 jq 1.4 中不起作用,因此建议使用 --arg EMAILID "$EMAILID"
如果您需要使用 jq 1.4 ,请构建。希望这可以帮助;只是花了我一天的时间来为自己解决这个问题;)
使用--arg
传递的参数将作为字符串传递。如果要传递不同 JSON 类型的数据,请使用 --argjson
,它将字符串解析为 JSON,例如,--argjson myObj '"a": [1, 2]'
【参考方案2】:
我通过转义内部双引号解决了这个问题
projectID=$(cat file.json | jq -r ".resource[] | select(.username==\"$EMAILID\") | .id")
【讨论】:
我使用它是因为 --arg 不能很好地与-c
【参考方案3】:
在这里发布它可能会帮助其他人。在字符串中,可能需要将引号传递给 jq。使用 jq 执行以下操作:
.items[] | select(.name=="string")
在 bash 中你可以这样做
EMAILID=$1
projectID=$(cat file.json | jq -r '.resource[] | select(.username=='\"$EMAILID\"') | .id')
基本上是转义引号并将其传递给 jq
【讨论】:
完美运行。对于寻求快速解决方案的人来说并不太复杂。【参考方案4】:有点无关,但我还是把它放在这里, 对于其他实际目的,shell 变量可以用作 -
value=10
jq '."key" = "'"$value"'"' file.json
【讨论】:
【参考方案5】:这是一个报价问题,你需要:
projectID=$(
cat file.json | jq -r ".resource[] | select(.username=='$EMAILID') | .id"
)
如果您使用 单引号 来分隔主字符串,则 shell 会按字面意思使用 $EMAILID
。
“双引号”每个包含空格/元字符和每个扩展的文字:"$var"
、"$(command "$var")"
、"$array[@]"
、"a & b"
。将'single quotes'
用于代码或文字$'s: 'Costs $5 US'
、ssh host 'echo "$HOSTNAME"'
。见http://mywiki.wooledge.org/Quoteshttp://mywiki.wooledge.org/Argumentshttp://wiki.bash-hackers.org/syntax/words
【讨论】:
在我的情况下也是错误的,如果根本不使用引号也类似:termux-contact-list |jq -r '.[] | select(.name=='$1')|.number'
。结果:jq Compile error
我不知道为什么这条评论被投票了这么多次;是的,双引号允许变量扩展,但jq
不喜欢单引号:jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?)
如果您的输入是常规 json,那么它的值将是双引号(不是单引号)。工作原理:对 jq 的整个 arg 使用双引号并转义(使用 `\`)内的任何双引号,如 @asid 回答。
它不起作用。 如果你用单引号分隔主字符串,shell 会按字面意思使用 $EMAILID。 假设你设置了 $EMAILID="myemail@hotmail.com",那么命令 cat file.json | jq -r ".resource[] | select(.username=='$EMAILID') | .id"
实际上会以 cat file.json | jq -r ".resource[] | select(.username==myemail@hotmail.com) | .id"
运行并导致jq
的编译错误。
这让我走上了解决问题的道路。我的最终工作字符串 UPLOADED_ARNS=$(aws devicefarm list-uploads --arn $PROJECT_ARN | \ jq ".uploads[] | arn: .arn, name: .name | select (.name | contains(\" $FILE_EXTENSION\"))" | \ jq --raw-output '.arn')【参考方案6】:
实现此目的的另一种方法是使用 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
【讨论】:
【参考方案7】:jq现在有更好的方法来访问环境变量,可以使用env.EMAILID
:
projectID=$(cat file.json | jq -r ".resource[] | select(.username==env.EMAILID) | .id")
【讨论】:
【参考方案8】:我知道有点晚才回复,抱歉。但这对我有用。
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')"
在我的例子中,我需要使用双引号和引号来访问变量值。
干杯。
【讨论】:
【参考方案9】:如果我们想将一些字符串附加到变量值并且我们使用转义的双引号,例如将.crt
附加到变量CERT_TYPE
;以下应该有效:
$ CERT_TYPE=client.reader
$ cat certs.json | jq -r ".\"$CERT_TYPE\".crt" #### This will *not* work #####
$ cat certs.json | jq -r ".\"$CERT_TYPE.crt\""
【讨论】:
【参考方案10】:我也遇到了同样的 jq 变量替换问题。我发现--arg
是必须与方括号[]
一起使用的选项,否则它将不起作用。我在下面给你示例:
RUNNER_TOKEN=$(aws secretsmanager get-secret-value --secret-id $SECRET_ID | jq '.SecretString|fromjson' | jq --arg kt $SECRET_KEY -r '.[$kt]' | tr -d '"')
【讨论】:
以上是关于将 bash 变量传递给 jq的主要内容,如果未能解决你的问题,请参考以下文章