【问题标题】:jq: pass string argument without quotesjq:传递不带引号的字符串参数
【发布时间】:2018-09-04 20:26:19
【问题描述】:

我想传递一个不带引号的参数(JQ arg 默认有双引号),因为它应该用作过滤器。例如

propt='.properties'
final=($(jq -r -c --arg p $propt '$p' sample.json))
echo $final

sample.json

{
  "type": "object",
  "description": "Contains information",
  "properties": {
    "type": {
      "description": "Type"
        }
   }
}

所以最终它会打印出.properties 而不是预期的{"type":{"description":"Type"}} 为此,我使用 bash shell。

请让我知道我做错了什么。

【问题讨论】:

  • 您需要区分 literalsyntactic 引号。语法引号根本不会传递给jq,它们会传递给bash。因此,jq 不能做任何不需要它们的事情,因为它无法控制 bash 在调用它之前如何解析命令。
  • 顺便说一句,这里的 Markdown 不是 GitHub 风格的:三重反引号没有任何特殊含义,并且不启用多行块的代码格式化。使用带有选定块的{} 按钮将每行缩进四个空格以启用语法突出显示。
  • ...顺便说一句,final=( $(...) ); echo $final 也有问题——它对jq 的输出进行字符串拆分和全局扩展以生成单词列表,并将该列表分配给数组,但随后只打印该数组的第一个元素。 final=$(...); echo "$final" 不会被破坏,因为它明确使用字符串而不是数组。或者,mapfile -t final < <(jq ...); printf 'Item: %s\n' "${final[@]}" 的 bug 也更少,它构建了一个数组,每行输出一个条目来自 jq,并将数组中的每个部分作为单独的参数传递给 printf
  • (啊——实际上,霍布斯的回答让我明白了问题中“不带引号”的含义。没有创建字面引号;考虑jq 好像--arg foo stringstring 周围添加引号是对执行模型的严重误解。如果您曾经为构建AST 的语言构建解析器,请这样想——引号是执行模型的一部分语法,它们不是数据的一部分;这在 jq 级别是正确的,而不仅仅是 shell 级别)。

标签: jq


【解决方案1】:

如果我理解正确的话,你会因为认为需要在 jq 中设置一个变量而不是让 shell 进行扩展而走神:

% foo='.properties'
% jq -r -c  "$foo" sample.json 

输出:

{"type":{"description":"Type"}}

注意 $foo 上的双引号仍然允许 shell 将变量扩展为 .properties。也就是说你可以不安全地使用:jq -r -c $foo sample.json

【讨论】:

  • 我的回答是假设原件中的间接/分离有某种原因......但如果没有,那么这是一个非常好的答案:)
【解决方案2】:

您不能以这种方式使用--arg--arg 的值是字符串,而不是 jq 过滤器表达式。如果您执行--arg p .properties,那么$p 将包含字符串".properties",它不会被评估为程序。找到一种不同的方式来做你想做的事,也许通过定义一个函数。

例如,如果你在你的程序前加上def p: .properties;,那么你可以在你的程序中使用.|p,就像你现在使用$p一样,它会访问.properties的任何值在上下文中。

【讨论】:

  • 我尝试使用上面提到的自定义函数。但我遇到的问题是 .properties 是动态的,它可能是不同上下文的不同路径,因此可以定义函数,但由于它是动态的,因此也需要传递参数。
  • @user915534 那么我想你需要问一个更清楚的问题,抱歉。
  • 当然,我必须发布一个新问题吗?最终,我正在寻找一种将变量参数传递给 JQ 程序的方法,并且该参数将用作过滤器。
  • @user915534 考虑到这里发生的混乱,可能需要一个新问题,但您也可以选择编辑当前问题以澄清。我建议提供一些关于您为什么这样做的背景,以帮助人们提供一个好的答案。
【解决方案3】:

由于 jq 没有“eval”函数,因此在 jq 中以编程方式指定路径的适当方法是将 JSON 数组与 jq 的 getpathsetpath 内置函数(视情况而定)结合使用。

因此,在您的情况下,您可以使用 --argjson 命令行选项来传递感兴趣的路径,例如

-—argson p '["properties"]'

你的 jq 程序会使用getpath($p)

不用说,这种方法适用于任意嵌套的路径。

【讨论】:

    猜你喜欢
    • 2019-11-20
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 2022-10-24
    • 2016-07-22
    • 1970-01-01
    相关资源
    最近更新 更多