jq查询的Bash变量替换始终返回null

问题描述 投票:0回答:2

从公司系统导出文件会在我无法更改的结构中生成json。在基于bash(v5.0.2)中的变量搜索特定属性时,在使用任何替换元素时,它始终返回null。如果我硬编码要搜索的值,它就可以工作。但是,需要能够使用变量来支持代码逻辑并且不必硬编码细节,特别是要给出1000个要处理的记录。

使用下面json的示例摘录,以及下面的代码,这显示了我根据jq手册中可以理解的内容尝试的内容。

{
  "status": true,
  "payload": {
    "customerData": {
      "101": {
        "title": "A Company",
        "id": "101",
        "storageGroups": "SHIPPING",
        "priority": "4",
        "originalname": "A Previous Company",
        "allowShipping": true,
        "parentCompany": "0",
        "rating": 0,
        "external": false,
        "application": "primary",
        "applicationName": "form27",
        "live": true,
        "logo": "http://url",
        "beta": false,
        "length": null,
        "token": "QSBQcmV2aW91cyBDb21wYW55LzEwMQ==",
        "active": "1"
      }
    }
  }
}

到目前为止测试方法的简单bash脚本

#!/bin/bash
chkCustomer=101
chkFile="json-simple.txt"
if [[ ! -s "${chkFile}" ]] ; then exit 1 ; fi
tokenTry1=$(cat "${chkFile}" | jq -r '.payload.customerData."${chkCustomer}".token')
printf "%s\n" "Try 1 Returned ${tokenTry1}"
tokenTry2=$(cat "${chkFile}" | jq -r '.payload.customerData."$chkCustomer".token')
printf "%s\n" "Try 2 Returned ${tokenTry2}"
tokenTry3=$(cat "${chkFile}" | jq -r --arg CHK ${chkCustomer} '.payload.customerData."$CHK".token')
printf "%s\n" "Try 3 Returned ${tokenTry3}"
tokenTry4=$(cat "${chkFile}" | jq -r --arg CHK ${chkCustomer} '.payload.customerData."env.$CHK".token')
printf "%s\n" "Try 4 Returned ${tokenTry4}"
tokenTry5=$(cat "${chkFile}" | jq -r --arg CHK 101 '.payload.customerData."$CHK".token')
printf "%s\n" "Try 5 Returned ${tokenTry5}"
tokenTry6=$(cat "${chkFile}" | jq -r '.payload.customerData.101.token')
printf "%s\n" "Try 6 Returned ${tokenTry6}"
tokenWorks=$(cat "${chkFile}" | jq -r '.payload.customerData."101".token')
printf "%s\n" "Try 7 (works) Returned ${tokenWorks}"

只有尝试7才会产生有效的响应。所有其余的都是null或失败。

针对json输出脚本是

Try 1 Returned null
Try 2 Returned null
Try 3 Returned null
Try 4 Returned null
Try 5 Returned null
jq: error: Invalid numeric literal at EOF at line 1, column 5 (while parsing '.101.') at <top-level>, line 1:
.payload.customerData.101.token                     
jq: error: syntax error, unexpected LITERAL, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.payload.customerData.101.token                     
jq: 2 compile errors
Try 6 Returned 
Try 7 (works) Returned QSBQcmV2aW91cyBDb21wYW55LzEwMQ==

我需要(或期望)的是我可以使用变量并执行jq查询来获得结果。

我确定我错过了令人难以置信的明显事物,但我无法理解这一点。看看我在SO上找到的其他问题,还没有人提供帮助。

bash variables jq substitution
2个回答
3
投票

这样做的安全方法是从代码中带走变量带外变量。那是:

#!/bin/bash
chkCustomer=101
chkFile="json-simple.txt"

companyToken=$(jq -r --arg chkCustomer "$chkCustomer" \
               '.payload.customerData[$chkCustomer].token' "$chkFile")

printf "%s\n" "Company token for ${chkCustomer} is ${companyToken}."

单引号字符串中的$chkCustomer由shell单独留下,而是由jq本身解释为引用通过--arg传入的字符串值。

这可以防止包含chkCustomer代码的jq值生成实际上不符合输入文件内容的输出,或者 - 以后,当jq添加I / O原语时 - 执行文件I / O并更改磁盘的内容。


1
投票

在其他单引号中使用bash变量来拆分命令,然后转义实际变量替换的双引号,解决此问题。

使用与原始问题相同的json的工作代码示例。

#!/bin/bash
chkCustomer=101
chkFile="json-simple.txt"
companyToken=$(jq -r '.payload.customerData.'\"${chkCustomer}\"'.token' "${chkFile}")
printf "%s\n" "Company token for ${chkCustomer} is ${companyToken}."

无论bash变量本身是否引用,此方法都有效。如果没有双引号的转义,它就会失败。

© www.soinside.com 2019 - 2024. All rights reserved.