jq in / 1的行为不一致

时间:2019-05-01 06:59:30

标签: arrays jq

来自jq docs的以下示例按预期工作-

$ echo '[1,2]' | jq 'map(in([0,1]))'
[
  true,
  false
]

但是将值转换为字符串失败-

$ echo '["1", "2"]' | jq 'map(in(["0","1"]))'
jq: error (at <stdin>:1): Cannot check whether array has a string key

为确保这不是引号问题,我还尝试了-

$ echo "[\"1\", \"2\"]" | jq 'map(in(["0","1"]))'
jq: error (at <stdin>:1): Cannot check whether array has a string key

此外,以下代码段也失败了,这可能是由于将0强​​制转换为布尔值false-

$ echo '[0,1]' | jq 'map(in([1,2]))'       
[
  true,
  true
]

3 个答案:

答案 0 :(得分:3)

您误解了in/1在做什么。它不是在测试一个值是否是数组的成员,而是在测试该值是否是对象键的成员。因此,对于数组,数字是期望的(索引),对于对象,字符串是(键)。与has/1完全相同,但是交换了输入。

$ jq -n '[0,-1,20,9,16,10] | map(in([range(20;30)]))' # 10 item array
[
  true,
  false,
  false,
  true,
  false,
  false
]
$ jq -n '["foo","bar"] | map(in({foo:1,boo:2,bat:3}))'
[
  true,
  false
]

如果要测试数组中的成员资格,则没有内置函数,但您可以自己制作。尽管contains/1很接近,但由于它测试字符串是否为子字符串并且不相等,所以它并不完全。 any/2可用于执行此操作。

def has_value($value):
    any(.[]; . == $value);

def in_array($arr): # swapped input version
    . as $value | any($arr[]; . == $value);

答案 1 :(得分:1)

index/1是可以最方便地用于检查数组成员身份的内置函数。尽管不是严格意义上的布尔值,但是if//的语义使使用起来很方便。如果您要进行严格的布尔测试,则只需使用成语index(_) != null

index/1值得详细了解,因此请考虑相应地阅读jq手册和FAQ。还要注意,INDEX/1是没有关系的。

答案 2 :(得分:0)

实际上inside确实可以解决问题(显然是在v1.5中添加的)

/home/foo/my-mod/go.mod

产生

jq -n '[123,444,565,344,"333",111,1111,87] | map([.]|inside([111,333,344]))'