Jq: Remove keys if they match a regex?

Created on 28 Sep 2015  路  5Comments  路  Source: stedolan/jq

Hi! I've been trying to do this in jqplay and I've gotten quite stuck.

I have a json file that looks like this. I need to remove any of the members that have keys that end with tcp:7000 through tcp:7099. A regex like /,tcp:70\d\d$/ is sufficient.

Is there a pattern for "keep everything but delete certain items"?

I can extract the "members" with:

{"iptables::sets::sets": {"listeners": .["iptables::sets::sets"]["listeners"]["members"]}}

Here is a sample data set:

{
  "iptables::sets::sets": {
    "listeners": {
      "config": "hash:ip,port family inet hashsize 1024 maxelem 65536",
      "members": {
        "10.7.2.13,tcp:80": {
          "comment": "comment text here"
        },
        "10.7.2.14,tcp:80": {
          "comment": "comment text here"
        },
        "192.168.1.10,tcp:7003": {
          "comment": "comment text here"
        },
        "192.168.1.10,tcp:7020": {
          "comment": "comment text here"
        }
      }
    }
  }
}

Any help would be appreciated!

support

Most helpful comment

How about this:

jq '."iptables::sets::sets"."listeners"."members"|=with_entries(select(.key|test("tcp:70\\d\\d$")|not))'

This outputs:

{
  "iptables::sets::sets": {
    "listeners": {
      "config": "hash:ip,port family inet hashsize 1024 maxelem 65536",
      "members": {
        "10.7.2.13,tcp:80": {
          "comment": "comment text here"
        },
        "10.7.2.14,tcp:80": {
          "comment": "comment text here"
        }
      }
    }
  }
}

All 5 comments

How about this:

jq '."iptables::sets::sets"."listeners"."members"|=with_entries(select(.key|test("tcp:70\\d\\d$")|not))'

This outputs:

{
  "iptables::sets::sets": {
    "listeners": {
      "config": "hash:ip,port family inet hashsize 1024 maxelem 65536",
      "members": {
        "10.7.2.13,tcp:80": {
          "comment": "comment text here"
        },
        "10.7.2.14,tcp:80": {
          "comment": "comment text here"
        }
      }
    }
  }
}

Wow! That's brilliant!

(Watching you is like watching a magician at work!)

Could you add to the docs some examples of the with_entries(select(.key|test("tcp:70\\d\\d$")|not))' pattern? I think a lot of people would find that useful and it is non-obvious.

Thanks!

This pattern also works (but we should document delpaths):

jq -n '{a:{b0:1,b1:2,b2:3}}|delpaths([paths|select(.[0]=="a" and .[1][1:] == "2")])'

That is, use paths or paths(<path expression>) to list the paths in . then select the paths to delete, gather then into an array, and pass that to delpaths.

Could you add to the docs some examples

The FAQ had a similar example, but I added another one using with_entries(select(.key|test(_)|not))

@TomOnTime FYI, you're free to edit the FAQ. All users are.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

neowulf picture neowulf  路  3Comments

sonots picture sonots  路  3Comments

tbelaire picture tbelaire  路  4Comments

rubensayshi picture rubensayshi  路  3Comments

LoganBarnett picture LoganBarnett  路  3Comments