使用 jq 一次删除多个键
Deleting multiple keys at once with jq
我需要一次从一些 JSON 中删除多个键(使用 jq
),我正在尝试了解是否有比调用 map 和每次都删除。这是我的输入数据:
test.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"]] ))
由于 delpaths
的参数只是 JSON,这种方法对于编程删除特别有用,例如如果键名可用作 JSON 字符串。
除了@user3899165 的回答,我发现要从 "sub-object"
中删除一个键列表
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
不需要同时使用map
和del
。
您可以将多个路径传递给 del
,以逗号分隔。
这是一个使用 "dot-style" 路径符号的解决方案:
jq 'del( .[] .Country, .[] .number, .[] .Language )' test.json
- 不需要引号(您可能觉得这样更易读)
- 不对路径进行分组(要求您为每个路径重新输入一次
.[]
)
这是一个使用 "array-style" 路径表示法的示例,它允许您将路径与通用前缀组合在一起,如下所示:
jq 'del( .[] ["Country", "number", "Language"] )' test.json
- 合并 "last-common ancestor" 下的子路径(在本例中是顶级列表迭代器
.[]
)
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)]
If the key contains special characters or starts with a digit, you need to surround it with double quotes like this: ."foo$"
, or else .["foo$"]
.
这个问题在 google 结果中的排名很高,所以我想指出,在这几年中的某个时候,del
显然已被更改,以便您可以删除多个密钥只有:
del(.key1, .key2, ...)
因此,假设您的 jq 版本是合理的最新版本,请不要为找出语法变通办法而费尽心思。
我需要一次从一些 JSON 中删除多个键(使用 jq
),我正在尝试了解是否有比调用 map 和每次都删除。这是我的输入数据:
test.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"]] ))
由于 delpaths
的参数只是 JSON,这种方法对于编程删除特别有用,例如如果键名可用作 JSON 字符串。
除了@user3899165 的回答,我发现要从 "sub-object"
中删除一个键列表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
不需要同时使用map
和del
。
您可以将多个路径传递给 del
,以逗号分隔。
这是一个使用 "dot-style" 路径符号的解决方案:
jq 'del( .[] .Country, .[] .number, .[] .Language )' test.json
- 不需要引号(您可能觉得这样更易读)
- 不对路径进行分组(要求您为每个路径重新输入一次
.[]
)
这是一个使用 "array-style" 路径表示法的示例,它允许您将路径与通用前缀组合在一起,如下所示:
jq 'del( .[] ["Country", "number", "Language"] )' test.json
- 合并 "last-common ancestor" 下的子路径(在本例中是顶级列表迭代器
.[]
)
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)]
If the key contains special characters or starts with a digit, you need to surround it with double quotes like this:
."foo$"
, or else.["foo$"]
.
这个问题在 google 结果中的排名很高,所以我想指出,在这几年中的某个时候,del
显然已被更改,以便您可以删除多个密钥只有:
del(.key1, .key2, ...)
因此,假设您的 jq 版本是合理的最新版本,请不要为找出语法变通办法而费尽心思。