GGGforce
GGGforce

Reputation: 653

JQ: how can I remove keys based on regex?

I would like to remove all keys that start with "hide". Important to note that the keys may be nested at many levels. I'd like to see the answer using a regex, although I recognise that in my example a simple contains would suffice. (I don't know how to do this with contains, either, BTW.)

Input JSON 1:

{
  "a": 1,
  "b": 2,
  "hideA": 3,
  "c": {
    "d": 4,
    "hide4": 5
  }
}

Desired output JSON:

{
  "a": 1,
  "b": 2,
  "c": {
    "d": 4
  }
}

Input JSON 2:

{
  "a": 1,
  "b": 2,
  "hideA": 3,
  "c": {
    "d": 4,
    "hide4": 5
  },
  "e": null,
  "f": "hiya",
  "g": false,
  "h": [{
    "i": 343.232,
    "hide9": "private",
    "so_smart": true
  }]
}

Thanks!

Upvotes: 1

Views: 4438

Answers (2)

Jeff Mercado
Jeff Mercado

Reputation: 134521

Since you're just checking the start of the keys, you could use startswith/1 instead in this case, otherwise you could use test/1 or test/2. Then you could pass those paths to be removed to delpaths/1.

You might want to filter the key by strings (or convert to strings) beforehand to account for arrays in your tree.

delpaths([paths | select(.[-1] | strings | startswith("hide"))])
delpaths([paths | select(.[-1] | strings | test("^hide"; "i"))])

Upvotes: 7

peak
peak

Reputation: 116880

A straightforward approach to the problem is to use walk in conjunction with with_entries, e.g.

walk(if type == "object" 
     then with_entries(select(.key | test("^hide") | not))
     else . end)

If your jq does not have walk/1 simply include its def (available e.g. from https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq) before invoking it.

Upvotes: 3

Related Questions