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"
    ]
  }
}

Try it online at jqplay.org

这是使用 reduce, leaf_paths, getpath and delpaths 的另一种方法:

reduce leaf_paths as $p (.;
  if $p[-2]=="agents" and getpath($p)=="agent4" then delpaths([$p]) else . end
)

Try it online at jqplay.org

这是一个使用 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