将bash变量传递给jq选择

asi*_*idd 76 bash json environment-variables jq

我编写了一个脚本来检索某些值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"
Run Code Online (Sandbox Code Playgroud)

pea*_*eak 121

考虑将shell变量(EMAILID)作为jq变量传递(为了便于说明,这里也是EMAILID):

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

后记

为了记录,另一种可能性是使用jq的env函数来访问环境变量.例如,考虑这个bash命令序列:

EMAILID=foo@bar.com  # not exported
EMAILID="$EMAILID" jq -n 'env.EMAILID'
Run Code Online (Sandbox Code Playgroud)

输出是一个JSON字符串:

"foo@bar.com"
Run Code Online (Sandbox Code Playgroud)

  • 这是唯一100%安全的答案; 它让`jq`使用值正确地创建过滤器,而不是使用`bash`来创建`jq`解释为过滤器的字符串.(如果`EMAILID`的值包含`)`,请考虑会发生什么.) (3认同)
  • 仅供参考,jq 的 `env` 函数在 jq 1.4 和 1.5+ 之间更改,因此对 `env.EMAILID`(在此答案的示例中)的引用在 jq 1.4 中不起作用,因此建议使用 `--arg EMAILID "$EMAILID" ` 构造如果您需要使用 jq 1.4 。希望这可以帮助; 只花了我一天+的时间来为自己解决这个问题;) (3认同)
  • 使用“--arg”传递的参数将作为字符串传递。如果要传递不同 JSON 类型的数据,请使用 `--argjson`,它将把字符串解析为 JSON,例如 `--argjson myObj '{"a": [1, 2]}'` (3认同)
  • 感谢高峰。您提供的解决方案是我一直在寻找的正确答案。是的,它有效。 (2认同)
  • 我的用例,它有效!`function n2 { termux-contact-list |jq -r --arg v1 "$1" '.[] | select(.name==$v1)|.number' }` 调用:`n2 Name1` (2认同)
  • 就我而言,我必须在变量名周围使用括号,并且由于它位于选择内部,所以我也必须转义它,就像这样 `jq --arg var "${SHELL_VAR}" '.UserPools[] | select(.Name == "\($var)-some-string")'` (2认同)

Zai*_*aid 18

Posting it here as it might help others. In string it might be necessary to pass the quotes to jq. To do the following with jq:

.items[] | select(.name=="string")
Run Code Online (Sandbox Code Playgroud)

in bash you could do

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

essentially escaping the quotes and passing it on to jq


asi*_*idd 17

我通过转义内部双引号解决了这个问题

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

  • 我使用它是因为 --arg 与 `-c` 配合不好 (2认同)

小智 12

Jq 现在有更好的方法来访问环境变量,您可以使用env.EMAILID

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


Gil*_*not 9

这是一个报价问题,你需要:

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

如果你用单引号来分隔主字符串,那么shell就是$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

  • 使用单引号导致错误 (7认同)
  • 我不确定为什么这个评论被投票了很多次。是的,双引号允许变量扩展,但是`jq`不喜欢单引号:`jq:error:语法错误,意外的INVALID_CHARACTER(Unix shell引用问题?)` (5认同)

mar*_*xor 9

一点不相关,但我仍然会把它放在这里,出于其他实际目的,shell 变量可以用作 -

value=10
jq  '."key" = "'"$value"'"' file.json
Run Code Online (Sandbox Code Playgroud)


And*_*art 5

实现此目的的另一种方法是使用 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"
Run Code Online (Sandbox Code Playgroud)

看到这里,这是我找到这个解决方案的地方:https : //github.com/stedolan/jq/issues/626