【问题标题】:Passing bash variable to jq将 bash 变量传递给 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"

【问题讨论】:

标签: json bash environment-variables jq


【解决方案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/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
    • 我不知道为什么这条评论被投票了这么多次;是的,双引号允许变量扩展,但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 '"')
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-05-25
              • 2019-03-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多