使用jq进行字段名称的模式匹配

34

这是一个非常基础(可能有点儿愚蠢)的问题,但我无法让它正常工作...

我有一个具有以下结构的 JSON 文件:

{
    "data": {
        "what a burger": [1,2,3],
        "wap": [66],
        "the map": [11,20],
        "H. Incandenza": [1,1],
        "What a burger": [a,a,3]
    }
}

我想提取data中“name”与某个模式匹配的字段值。例如,我想提取所有不区分大小写的“what a burger”匹配项以获取:

[1,2,3],[a,a,3]

我的猜测会是类似这样的东西

jq '.data | match("what a burger";"i")'

但是这会导致

jq: error (at <stdin>:9): object ({"what a bu...) cannot be matched, as it is not a string

加油。

2个回答

36

你的语句无效,因为你试图将数据对象传入匹配函数,但是匹配函数只能在字符串上使用。

下面的表达式可以实现你的需求。 to_entries 将对象转换为键值数组。然后我们使用 map 迭代这个数组,并使用 select 选择所有键(现在是字符串)具有匹配项的条目。最后我们只需要打印每个元素的值即可。

.data | to_entries | map(select(.key | match("what a burger";"i"))) | map(.value)

然而,有两个注释:

  • [a,a,3]在JSON中是不被允许的,因为a不是一个数字。
  • 这个方法起作用是因为键实际上是不同的,即使只有字母大小写不相等。如果至少有两个键是相同的,就会出现问题,因为键应该是唯一的。事实上,jq将只输出其中一个元素。

3
两个map调用可以且应该合并。 - Jeff Mercado

23

这里有一个稍微更简洁的替代方案:

.data | with_entries(select(.key|match("what a burger";"i")))[]

在纠正输入并使用jq的-c选项后,这将生成两行:

[1,2,3]
["a","a",3]

4
我很喜欢这个方法,它帮助我找到了获取所有键值对的方法:如果键名包含某个模式(或者是唯一的)。获取所有键名为 "keynameSOMETHING" 的值: .data | with_entries(select(.key|match("keyname+";"ig")))[]如果要按多个模式搜索键名中的内容,只需删除末尾的 [] 即可,例如:.data | with_entries(select(.key|match("contains1+", "contains2+"; "ig")))没有您的建议,我无法完成它,非常感谢 @peak。 - Mikec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接