JQ 从对象内部运行动态命令

JQ run dynamic command from inside the object

提问人:Pitya Bhai 提问时间:11/1/2023 最后编辑:peakPitya Bhai 更新时间:11/2/2023 访问量:54

问:

在 JQ 中,是否可以从同一对象执行命令?

举个例子

{
"cmd": ".name += \" Smith\" | .name",
"name": "John"
}

如果你看到我有 name 和 cmd 作为两个键。如果在 JQPlay 中从 cmd 的值运行文本。您将看到以下对象"John Smith"

是否可以使用单个 JQ 查询来做到这一点?

JQ 评估

评论

1赞 pmf 11/1/2023
不,jq 没有可以从 JSON 字符串解码和运行 jq 过滤器的函数(或类似函数)。通过一个 jq 实例输出它,并让 shell 将其用作另一个实例的过滤器,这是你能做的最好的事情。eval
0赞 Pitya Bhai 11/2/2023
感谢@pmf的有用见解!

答:

0赞 peak 11/1/2023 #1

正如@pmf指出的,jq 没有提供“eval”函数,所以如果你真的想计算 jq 表达式,你必须编写自己的表达式,这可能不是你想要的。

但是,有一个合理的替代方案。由于您显然愿意在 JSON 中包含某种要计算的表达式,因此您可以借鉴 jq 对 array-path 的支持,并编写一个简单的计算器。例如 如果您愿意将 JSON 模板编写为:

{
  "name": [["firstname"], " Smith"],
  "firstname": "John"
}

然后是这点基础设施:

def ispath:
  type == "array" and all(.[]; type | IN("string","number") );
  
# eval . in the context of $context
def eval($context):
  . as $x
  | if type == "string" then .
    elif ispath then $context | getpath($x)
    elif type == "array"
    then map( eval($context) ) | add
    elif type == "object"
    then map_values(eval($context))
    else tostring
    end;

将允许您通过以下方式实现您想要的东西:

{
  "name": [["firstname"], " Smith"],
  "firstname": "John"
}
| eval(.)

评论

0赞 Pitya Bhai 11/2/2023
谢谢@peak我的情况有点复杂。.我有很多过滤器,我想应用。.