【发布时间】:2018-07-31 15:00:21
【问题描述】:
echo "[[{\"t\":4}]]" | jq 'index(.[0])'
我期待它返回 0。 相反,它返回 null。 索引仅适用于带有标量的数组,但是一旦存在嵌套数组,它就会返回 null。 为什么?
【问题讨论】:
echo "[[{\"t\":4}]]" | jq 'index(.[0])'
我期待它返回 0。 相反,它返回 null。 索引仅适用于带有标量的数组,但是一旦存在嵌套数组,它就会返回 null。 为什么?
【问题讨论】:
因为显然index 需要一个元素子序列来查找,标量是一个特殊情况,相当于一个元素序列。
比较三种情况:
echo "[0,2,0,3,0,6,0,2]" | jq 'index(2)'
echo "[0,2,0,3,0,6,0,2]" | jq 'index([2])'
echo "[0,2,0,3,0,6,0,2]" | jq 'index([2,0])'
它们都返回 1。
因此,在您的情况下,它试图在包含列表(而不是直接对象)的列表中查找由对象组成的单个元素子序列。
【讨论】:
在 jq 手册中,在标题 indices 下有一个关于 index 语义的提示。简而言之,看似错误的行为实际上是一个“特征”。也就是说,以下说明了预期的行为:
$ jq 'index([1,2])'
[1,2]
0
$ jq 'index([[1,2]])'
[[1,2]]
0
$
所以要搜索 JSON 实体 X,使用 index([X]) 总是安全的。不幸的是,由于index 当前的实现方式,它没有(应该)那么高效,但这是一个不同的话题。
不过,.[[X]] 和 IN/1 值得了解。
一个鲜为人知的事实是后缀方括号提供“索引”功能:
$ jq -nc '[1,2,30,3,3][[3]]'
[3,4]
$ jq -nc '[[1],2,30,3][[1]]'
[]
$ jq -nc '[[1],2,30,3][[[1]]]'
[0]
$ jq -nc '[{a:1},2,30,3][[ {a:1} ]]'
[0]
所以要恢复输入数组中X的最小索引:
.[[X]][0]
与 index/1 一样,如果 X 不在输入数组中,则返回 null:
$ jq -n '[1,2,3][ [4] ][0]'
null
jq 的“主”版本有一对简单的面向流的过滤器(命名为IN),用于检查项目是否在流中。这是IN/1 的有效定义,如果您的jq 有first/1,则可以使用它:
def IN(s): . as $in | first( if (s == $in) then true else empty end ) // false;
这里s 是要搜索的流。
【讨论】: