【问题标题】:bash - call of jq generates syntax errors and INVALID_CHARACTER messagesbash - 调用 jq 生成语法错误和 INVALID_CHARACTER 消息
【发布时间】:2020-08-29 07:33:28
【问题描述】:

我试图理解为什么我的脚本在调用 jq 时会卡住。

这里是代码。我以三种不同的方式调用 jq,只有下面的第一个选项有效。

#define vars
jq_filter_filename_start="jq_filter_start.txt"
jq_filter_filename_end="jq_filter_end.txt"
check_config_list="CronJobName CronJobResult"
dc1="test.json"
jq_filter_start=$(<"$jq_filter_filename_start")
jq_filter_end=$(<"$jq_filter_filename_end")

# now Filter resulting json for missing properties
    
#case 1 - works without using bash vars
for i in $check_config_list; do
    jq -r --arg search_param "$i" '[.[] | select ( .Body.values)] | [.[] | select (all(.Body.values[]; .name != $search_param ) )] | .[].Header.Tenant' "$dc1"
    done

#case 2 - does not work when using vars and calling jq directly
for i in $check_config_list; do
    jq -r --arg search_param "$i" "$jq_filter_start" $search_param "$jq_filter_end" "$dc1"
    done

#case 3 - does not work when putting everything in an array
for i in $check_config_list; do
    jqcommand=(jq -r "$jq_filter_start" \""$i"\" "$jq_filter_end" "$dc1")
    ${jqcommand[@]}
    done

这里是 jq_filter_start.txtjq_filter_end.txt 文件的内容 - 你可以猜到 - 它是 jq 过滤器的开始和结束:

'[.[] | select ( .Body.values)] | [.[] | select (all(.Body.values[]; .name !=
) )] | .[].Header.Tenant'

您能否解释一下为什么我在案例 2 和案例 3 中都得到以下输出?

jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
'[.[] | select ( .Body.values)] | [.[] | select (all(.Body.values[]; .name !=
jq: 1 compile error

我想分解 jq 的过滤器并将它们动态存储在 vars 或文件中,并在必要时加入它们,如上所述。

我的 jq 过滤器开始变得相当长和复杂,一个这样的例子

[.[] | select ( .Body.extensions ) ] | [.[] | select ( (.Header.Tenant | test("^(?![a-z]{3}-[a-z][a-z1-9]{2}-p[1-9]$)[a-zA-Z0-9.,-]+$")) and (.Header.ProductType | test("Product")))] | .[].Header.Tenant

在上面的示例中,我需要有一个选项来使用 vars 代替 .Body.extensions 并在 test() 条件内。

这就是为什么我尝试使用 bash vars 但似乎我遗漏了一些东西......

附:下面的示例 JSON。此脚本的目的是通过CronJobName CronJobResultcheck_config_list 中定义的其他参数来识别所有这些缺少一个或多个此类参数的租户。

[
    {
        "Header": {
            "Tenant": "mytenant"
        },
        "Body": {
            "values": [                
                {
                    "id": "aaaa0001-0a0a-0b0b-0c0c-07a3a4decaa6",
                    "name": "Currency"
                },
                {
                    "id": "aaaa0001-0a0a-0b0b-0c0c-9390805c3b09",
                    "name": "CronJobName"
                }
            ]
        }
    }
]

【问题讨论】:

  • 你的 JSON 在哪里?请更新它
  • 为什么要在变量之间拆分过滤代码?选项 1 是推荐的方法
  • 最好在名为script.jq 的文件中使用 jq 脚本并使用它执行
  • 我在调用 jq 时尽量不要有 300 个字符长的行。这就是我尝试使用 vars 的原因......就在 jq 脚本中调用 jq 过滤器而言 - 正如过滤器更改中概述的参数那样,我需要能够动态构建过滤器。
  • 在使用脚本时为什么不使用--arg 字段。您可以在命令行中传递参数,同时涉及脚本中的过滤器

标签: arrays bash for-loop error-handling jq


【解决方案1】:

使用诸如 jq_filter_start.txt 和 jq_filter_end.txt 之类的文件来保存程序片段几乎肯定是一个坏主意(通常),原因有很多,尤其是它会导致问题中显示的那种错误.考虑到这一点,让我们考虑一种解决“案例 2”的方法。

由于我想到的解决方法比解释您遇到的问题更容易,因此我将重点关注前者。

可以通过以下三个步骤来完成修复:

  1. 省略 jq_filter_start.txt 中的前导 '

  2. 省略 jq_filter_end.txt 中的尾随 '

  3. 将 jq 的调用改为:

jq -r --arg search_param "$i" "$jq_filter_start \$search_param $jq_filter_end" "$dc1"

关键是 jq 程序,当在命令行上显示时,必须以单个“字符串”的形式显示。

但是,与其进一步关注这些最好避免的路径,不如将注意力重新集中在促使这些探索的实际问题上。

【讨论】:

  • 感谢@peak 提供解决方案。我的问题 - 我需要传递给 jq 的不仅仅是一个,而是 2-4 个不同的参数 - 使用正则表达式查看问题末尾的过滤器并进行测试。您是否建议将上述方法和所有这些参数用于 jq?还是像上面 Inian 建议的那样在 filter.jq 中编写所有内容并使用 -f 调用它会更好吗?谢谢
  • @Invisible999 - 请参阅单独的答案/
【解决方案2】:

你是否使用 -f 命令行选项在这里真的是一个切线问题。

例如,您可以通过在 jq 中执行迭代来避免摆弄程序片段,例如:

jq -r '("CronJobName", "CronJobResult") as $search_param
  | [.[] | select( .Body.values)]
  | [.[] | select (all(.Body.values[]; .name != $search_param ) )]
  | .[].Header.Tenant' "$dc1"

或者如果您希望在外部提供搜索参数值:

jq -r --argjson search_params '["CronJobName", "CronJobResult"]' jq '
  $search_params[] as $search_param
  | [.[] | select ( .Body.values)]
  | [.[] | select (all(.Body.values[]; .name != $search_param ) )]
  | .[].Header.Tenant' "$dc1"

还请注意,如果您希望参数化一些 jq 代码,例如 .foo.bar,您可以使用 .[$FOOSTRING][$BARSTRING] 或 getpath($ARRAY) 等形式,这样您就可以传入以编程方式设置参数。

您可能还想利用 jq 对用户定义函数的支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 2020-05-21
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    相关资源
    最近更新 更多