文档确实听起来好像没有。但是,我想不出任何方法来解释下面的行为。我做错了什么?
在某些集群数据上,我试图显示可用总数中正在使用的 cpu 总数。我想迭代
o.json
中的对象数组并计算两个值之间的差异 (.cpus.total - .cpus.allocated
) 并显示这些增量的总和以及其中一个值的总和 (.cpus.total
)。
所以
.[].cpus.total
会输出一个整数列表:
$ cat /tmp/o.json | jq -c '[.[].cpus.total]|add'
2764
但是当我在 map 语句之后做同样的事情时,它会出错:
$ cat /tmp/o.json | jq -c '[(map(.cpus.total - .cpus.allocated) | add), "/", [.[].cpus.total]|add]'
jq: error (at <stdin>:13762): Cannot iterate over number (2556)
这个错误听起来像是“add”想要一个数组但没有得到。果然,将其强制放入数组(然后取第零个值,因为它只是一个整数)是有效的:
$ cat /tmp/o.json | jq -c '[(map(.cpus.total - .cpus.allocated) | add), "/", [[.[].cpus.total]|add][0] ]'
[2556,"/",2764]
此时我已经有了工作代码,但我不明白为什么我需要那组额外的方括号来让它运行,但是仅如果程序中前面有地图的话。什么给出?
jq map 函数会改变输入对象吗?
不。事实上,价值观永远不会改变。 jq 是一种纯粹的函数式语言,尽管它的作用域规则可能会让任何不熟悉它们的人看起来有所不同。
当我们编写像
{} | .x = 1 | .x = 2
这样的表达式时,可能看起来好像输入对象正在被修改,并且插入 debug
语句将显示与“x”关联的值从 null 更改为 1,然后是 2。因此请考虑:
jq -nc '{} | . as $zero | .x = 1 | . as $one | .x = 2 | . as $two | ($zero, $one, $two)'
{}
{"x":1}
{"x":2}