jq 递归地删除出现在架构中任何位置的数组中的值
jq recursively delete values that appear in array anywhere in schema
我正在尝试了解如何使用 jq 删除数组中架构中任意位置出现的特定值。
在这种情况下,我试图从标记为 agents 的字段下方的数组中的任何位置删除 agent4。
这是我目前所拥有的
jq '..|.agents? | select(. != null) | map(select(. != "agent4"))'
但这只会创建更改的数据,我不知道如何将其重新分配给路径。
我最初尝试为此使用 sed,但它绝对不是可以使用的工具,所以我切换到 jq。
{
"environments": {
"default": {
"machines": {
"dev-machine": {
"agents": [
"agent1",
"agent2",
"agent3",
"agent4"
]
}
}
}
},
"environments2": {
"agents": [
"agent1",
"agent2",
"agent3",
"agent4"
]
}
}
然而这只是输出
[
"agent1",
"agent2",
"agent3"
]
[
"agent1",
"agent2",
"agent3"
]
这是一个使用 path to find "agent4" and verify it appears within "agents" before removing it with delpaths
的解决方案
delpaths([ path(..|select(.=="agent4")) | select(.[-2]=="agents") ])
样本运行(假设数据在data.json
)
$ jq -M 'delpaths([ path(..|select(.=="agent4")) | select(.[-2]=="agents") ])' data.json
{
"environments": {
"default": {
"machines": {
"dev-machine": {
"agents": [
"agent1",
"agent2",
"agent3"
]
}
}
}
},
"environments2": {
"agents": [
"agent1",
"agent2",
"agent3"
]
}
}
这是使用 reduce, leaf_paths, getpath and delpaths 的另一种方法:
reduce leaf_paths as $p (.;
if $p[-2]=="agents" and getpath($p)=="agent4" then delpaths([$p]) else . end
)
这是一个使用 walk
的解决方案:
walk( if type == "object" and has("agents")
then .agents |= map(select(. != "agent4"))
else . end )
如果您想从所有数组中删除值,无论它们出现在哪里:
walk( if type == "array" then map(select(. != "agent4")) else . end )
如果您想要更灵活的解决方案,例如,您可以将 "agent4"
替换为 $value
,然后在命令行上设置 $value
,例如如果 VALUE 是字符串,则使用 --arg value VALUE
,或根据需要使用 --argjson value VALUE
。
如果您的 jq 没有 walk
,只需在前面加上它的定义即可(例如)从 https://github.com/stedolan/jq/blob/master/src/builtin.jq
我正在尝试了解如何使用 jq 删除数组中架构中任意位置出现的特定值。
在这种情况下,我试图从标记为 agents 的字段下方的数组中的任何位置删除 agent4。
这是我目前所拥有的
jq '..|.agents? | select(. != null) | map(select(. != "agent4"))'
但这只会创建更改的数据,我不知道如何将其重新分配给路径。
我最初尝试为此使用 sed,但它绝对不是可以使用的工具,所以我切换到 jq。
{
"environments": {
"default": {
"machines": {
"dev-machine": {
"agents": [
"agent1",
"agent2",
"agent3",
"agent4"
]
}
}
}
},
"environments2": {
"agents": [
"agent1",
"agent2",
"agent3",
"agent4"
]
}
}
然而这只是输出
[
"agent1",
"agent2",
"agent3"
]
[
"agent1",
"agent2",
"agent3"
]
这是一个使用 path to find "agent4" and verify it appears within "agents" before removing it with delpaths
的解决方案delpaths([ path(..|select(.=="agent4")) | select(.[-2]=="agents") ])
样本运行(假设数据在data.json
)
$ jq -M 'delpaths([ path(..|select(.=="agent4")) | select(.[-2]=="agents") ])' data.json
{
"environments": {
"default": {
"machines": {
"dev-machine": {
"agents": [
"agent1",
"agent2",
"agent3"
]
}
}
}
},
"environments2": {
"agents": [
"agent1",
"agent2",
"agent3"
]
}
}
这是使用 reduce, leaf_paths, getpath and delpaths 的另一种方法:
reduce leaf_paths as $p (.;
if $p[-2]=="agents" and getpath($p)=="agent4" then delpaths([$p]) else . end
)
这是一个使用 walk
的解决方案:
walk( if type == "object" and has("agents")
then .agents |= map(select(. != "agent4"))
else . end )
如果您想从所有数组中删除值,无论它们出现在哪里:
walk( if type == "array" then map(select(. != "agent4")) else . end )
如果您想要更灵活的解决方案,例如,您可以将 "agent4"
替换为 $value
,然后在命令行上设置 $value
,例如如果 VALUE 是字符串,则使用 --arg value VALUE
,或根据需要使用 --argjson value VALUE
。
如果您的 jq 没有 walk
,只需在前面加上它的定义即可(例如)从 https://github.com/stedolan/jq/blob/master/src/builtin.jq