提问人:antun 提问时间:3/26/2016 最后编辑:slmantun 更新时间:1/6/2022 访问量:56302
使用 jq 一次删除多个密钥
Deleting multiple keys at once with jq
问:
我需要从一些 JSON 中一次删除多个键(使用 ),我正在尝试了解是否有比每次都调用 map 和 del 更好的方法。这是我的输入数据:jq
测试.json
[
{
"label": "US : USA : English",
"Country": "USA",
"region": "US",
"Language": "English",
"locale": "en",
"currency": "USD",
"number": "USD"
},
{
"label": "AU : Australia : English",
"Country": "Australia",
"region": "AU",
"Language": "English",
"locale": "en",
"currency": "AUD",
"number": "AUD"
},
{
"label": "CA : Canada : English",
"Country": "Canada",
"region": "CA",
"Language": "English",
"locale": "en",
"currency": "CAD",
"number": "CAD"
}
]
对于每个项目,我想删除数字、语言和国家/地区键。我可以使用以下命令来做到这一点:
$ cat test.json | jq 'map(del(.Country)) | map(del(.number)) | map(del(.Language))'
这工作正常,我得到了所需的输出:
[
{
"label": "US : USA : English",
"region": "US",
"locale": "en",
"currency": "USD"
},
{
"label": "AU : Australia : English",
"region": "AU",
"locale": "en",
"currency": "AUD"
},
{
"label": "CA : Canada : English",
"region": "CA",
"locale": "en",
"currency": "CAD"
}
]
但是,我正在尝试了解是否有一种方法可以指定要删除的多个标签,因此我不必有多个指令?jq
map(del())
答:
您可以提供要删除的路径流:
$ cat test.json | jq 'map(del(.Country, .number, .Language))'
此外,请考虑一下,您可能更愿意将所需的密钥列入白名单,而不是将特定密钥列入黑名单:
$ cat test.json | jq 'map({label, region, locale, currency})'
delpaths
也值得了解,也许不那么神秘:
map( delpaths( [["Country"], ["number"], ["Language"]] ))
由于参数 to 只是 JSON,因此这种方法对于编程删除特别有用,例如,如果键名称以 JSON 字符串形式提供。delpaths
评论
delpaths
将设置为在提供的路径表达式中找到的键的值,它不会删除键,如此处要求。null
del
jq 'del( .[] ["Country", "number", "Language"] )' test.json
delpaths
null
del
delpaths
map
null
除了@user3899165的回答之外,我还发现要从“子对象”中删除键列表
example.json
{
"a": {
"b": "hello",
"c": "world",
"d": "here's",
"e": "the"
},
"f": {
"g": "song",
"h": "that",
"i": "I'm",
"j": "singing"
}
}
$ jq 'del(.a["d", "e"])' example.json
评论
d | e
jq 'del(.*'["d", "e"])' example.json
jq 'del(.[]["d", "e"])' example.json
没有必要同时使用 和 。map
del
您可以将多个路径传递给 ,用逗号分隔。del
以下是使用“点式”路径表示法的解决方案:
jq 'del( .[] .Country, .[] .number, .[] .Language )' test.json
- 不需要引号(您可能会觉得引号更易读)
- 不对路径进行分组(要求每个路径重新键入一次)
.[]
下面是一个使用“数组样式”路径表示法的示例,它允许您将路径与通用前缀组合在一起,如下所示:
jq 'del( .[] ["Country", "number", "Language"] )' test.json
- 将子路径组合在“最后一个共同祖先”(在本例中为顶级列表迭代器)下
.[]
)
Peak 的答案使用了 和 ,尽管您似乎也可以单独使用它:map
delpaths
delpaths
jq '[.[] | delpaths( [["Country"], ["number"], ["Language"]] )]' test.json
- 需要引号和单例数组数组
- 要求您将其放回列表中(使用开始和结束方括号)
总的来说,为了简洁起见,我在这里会选择数组样式的表示法,但了解做同一件事的多种方法总是好的。
Louis 在他的回答中提到的“数组式”和“点式”符号之间的更好折衷。
del(.[] | .Country, .number, .Language)
此表单还可用于从嵌套对象中删除键列表(参见 russholio 的回答):
del(.a | .d, .e)
这意味着您还可以选择单个索引来删除以下键:
del(.[1] | .Country, .number, .Language)
或多个:
del(.[2,3,4] | .Country,.number,.Language)
您可以使用以下函数删除范围(切片表示法不起作用):range()
del(.[range(2;5)] | .Country,.number,.Language) # same as targetting indices 2,3,4
一些旁注:
map(del(.Country,.number,.Language))
# Is by definition equivalent to
[.[] | del(.Country,.number,.Language)]
如果键包含特殊字符或以数字开头,则需要用双引号将其括起来,如下所示: 或 否则 。
."foo$"
.["foo$"]
这个问题在谷歌结果中非常高,所以我想指出,在随后的几年中,显然已经发生了变化,因此您可以使用以下命令删除多个键:del
del(.key1, .key2, ...)
因此,不要试图弄清楚语法解决方法,假设您的 jq 版本是相当最新的。
评论
jq
Cannot index string with string
评论