如何使用jq检查数组中是否存在元素
How to check if element exists in array with jq
我有一个数组,我需要检查该数组中是否存在元素或使用以下方法从数组中获取该元素
jq, fruit.json:
{
"fruit": [
"apple",
"orange",
"pomegranate",
"apricot",
"mango"
]
}
cat fruit.json | jq '.fruit .apple'
无效
[警告:查看评论和备选答案。]
cat fruit.json | jq '.fruit | contains(["orange"])'
'contains' 的语义一点都不简单。一般来说,最好使用 'index' 来测试数组是否具有特定值,例如
.fruit | index( "orange" )
但是,如果感兴趣的item本身就是一个数组,一般形式:
ARRAY | index( [ITEM] )
应该使用,例如:
[1, [2], 3] | index( [[2]] ) #=> 1
IN/1
如果您的 jq 有 IN/1
那么更好的解决方案是使用它:
.fruit as $f | "orange" | IN($f[])
如果您的 jq 具有 first/1
(jq 1.5 也是如此),那么这里是要使用的 IN/1
的快速定义:
def IN(s): first((s == .) // empty) // false;
any(_;_)
另一种有时更方便的有效替代方法是使用 any/2
,例如
any(.fruit[]; . == "orange")
或等同于:
any(.fruit[] == "orange"; .)
对于未来的访问者,如果您碰巧在变量中有数组并想对照它检查输入,并且您有jq 1.5(没有IN),你最好选项是 index
但有第二个变量:
.inputField as $inputValue | $storedArray|index($inputValue)
这在功能上等同于 .inputField | IN($storedArray[])
。
如果数组 fruit
包含 "apple"
,则 jq
return 成功,否则错误:
jq -e '.fruit|any(. == "apple")' fruit.json >/dev/null
要输出找到的元素,请更改为
jq -e '.fruit[]|select(. == "apple")' fruit.json
如果搜索固定字符串,这不是很相关,但如果 select
表达式可能匹配不同的值,例如如果是正则表达式。
要仅输出不同的值,请将结果传递给 unique
。
jq '[.fruit[]|select(match("^app"))]|unique' fruit.json
会搜索所有以app
开头的水果,并输出唯一值。 (请注意,原始表达式必须包含在 []
中才能传递给 unique
。)
在这里扩展答案,如果您需要过滤水果数组 反对另一个水果数组,您可以做一些事情像这样:
cat food.json | jq '[.fruit[] as $fruits | (["banana", "apple"] | contains([$fruits])) as $results | $fruits | select($results)]'
这将 return 一个仅包含上述示例中的“apple”的数组 json。
这个修改过的示例在这里确实有效:
jq -r '.fruit | index( "orange" )' fruit.json | tail -n 1
它只获取输出的最后一行。
如果存在,则 returns 0
。
如果不这样做,它 returns null
.
我有一个数组,我需要检查该数组中是否存在元素或使用以下方法从数组中获取该元素 jq, fruit.json:
{
"fruit": [
"apple",
"orange",
"pomegranate",
"apricot",
"mango"
]
}
cat fruit.json | jq '.fruit .apple'
无效
[警告:查看评论和备选答案。]
cat fruit.json | jq '.fruit | contains(["orange"])'
'contains' 的语义一点都不简单。一般来说,最好使用 'index' 来测试数组是否具有特定值,例如
.fruit | index( "orange" )
但是,如果感兴趣的item本身就是一个数组,一般形式:
ARRAY | index( [ITEM] )
应该使用,例如:
[1, [2], 3] | index( [[2]] ) #=> 1
IN/1
如果您的 jq 有 IN/1
那么更好的解决方案是使用它:
.fruit as $f | "orange" | IN($f[])
如果您的 jq 具有 first/1
(jq 1.5 也是如此),那么这里是要使用的 IN/1
的快速定义:
def IN(s): first((s == .) // empty) // false;
any(_;_)
另一种有时更方便的有效替代方法是使用 any/2
,例如
any(.fruit[]; . == "orange")
或等同于:
any(.fruit[] == "orange"; .)
对于未来的访问者,如果您碰巧在变量中有数组并想对照它检查输入,并且您有jq 1.5(没有IN),你最好选项是 index
但有第二个变量:
.inputField as $inputValue | $storedArray|index($inputValue)
这在功能上等同于 .inputField | IN($storedArray[])
。
如果数组 fruit
包含 "apple"
,则 jq
return 成功,否则错误:
jq -e '.fruit|any(. == "apple")' fruit.json >/dev/null
要输出找到的元素,请更改为
jq -e '.fruit[]|select(. == "apple")' fruit.json
如果搜索固定字符串,这不是很相关,但如果 select
表达式可能匹配不同的值,例如如果是正则表达式。
要仅输出不同的值,请将结果传递给 unique
。
jq '[.fruit[]|select(match("^app"))]|unique' fruit.json
会搜索所有以app
开头的水果,并输出唯一值。 (请注意,原始表达式必须包含在 []
中才能传递给 unique
。)
在这里扩展答案,如果您需要过滤水果数组 反对另一个水果数组,您可以做一些事情像这样:
cat food.json | jq '[.fruit[] as $fruits | (["banana", "apple"] | contains([$fruits])) as $results | $fruits | select($results)]'
这将 return 一个仅包含上述示例中的“apple”的数组 json。
这个修改过的示例在这里确实有效:
jq -r '.fruit | index( "orange" )' fruit.json | tail -n 1
它只获取输出的最后一行。
如果存在,则 returns 0
。
如果不这样做,它 returns null
.