Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq recursively delete values that appear in array anywhere in schema

I'm trying to find out how to use jq to remove a certain value that occurs anywhere in the schema in an array.

In this case i'm trying to remove agent4 from anywhere inside an array underneath the field labelled agents.

This is what I have so far

jq '..|.agents? | select(. != null) |  map(select(. != "agent4"))'

But that just creates the changed data and I don't know how to re-assign it to the path.

I originally tried using sed for this but its definitely not the tool to use so I switched to jq.

   {
      "environments": {
        "default": {
          "machines": {
            "dev-machine": {
              "agents": [
                "agent1",
                "agent2",
                "agent3",
                "agent4"
              ]
            }
          }
        }
      },
      "environments2": {         
         "agents": [
            "agent1",
            "agent2",
            "agent3",
            "agent4"
         ] 
      }
    }

However this just outputs

[
  "agent1",
  "agent2",
  "agent3"
]
[
  "agent1",
  "agent2",
  "agent3"
]

1 Answers

Here's a solution using walk:

walk( if type == "object" and has("agents") 
      then .agents |= map(select(. != "agent4"))
      else . end )

If you want to remove the value from all arrays, wherever they occur:

walk( if type == "array" then map(select(. != "agent4")) else . end )

If you want a more flexible solution, you could, for example, replace "agent4" by $value, and then set $value on the command-line, e.g. using --arg value VALUE if VALUE is a string, or --argjson value VALUE as appropriate.

If your jq does not have walk, simply prepend its definition, which is available (for example) from https://github.com/stedolan/jq/blob/master/src/builtin.jq

like image 152
peak Avatar answered Sep 03 '25 17:09

peak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!