bchill
bchill

Reputation: 35

Get values from only the related parents when matching a child

I am trying to get a value from an array by matching a value in a child array, but everything I try either returns nothing or all of members of the parent array. I only want the info from the parent where the child matches.

Specifically, I want to list all of the AWS security groups that have port 22 rules in them.

This is a reduced sample output from the aws command line that I am trying to parse:

{
    "SecurityGroups": [
        {
            "Description": "ssh and web group",
            "IpPermissions": [
                {
                    "FromPort": 22,
                    "ToPort": 22
                },
                {
                    "FromPort": 80,
                    "ToPort": 80
                }
            ],
            "GroupName": "ssh-web",
            "GroupId": "sg-11111111"
        },
        {
            "Description": "https group",
            "IpPermissions": [
                {
                    "FromPort": 443,
                    "ToPort": 443
                },
                {
                    "FromPort": 8443,
                    "ToPort": 8443
                }
            ],
            "GroupName": "https",
            "GroupId": "sg-22222222"
        }
    ]
}

I have tried this:

aws ec2 describe-security-groups |
    jq '.SecurityGroups[] as $top |
        .SecurityGroups[].IpPermissions[] |
        select(.FromPort == 22) |
        $top'

and this:

aws ec2 describe-security-groups |
    jq '. as $top |
        .SecurityGroups[].IpPermissions[] |
        select(.FromPort == 22) |
        $top'

Both commands show both of the top-level array entries instead of just one containing the port 22 entry; they just show the entire output from the aws command.

The person who answered this question below specifically refers to the potential scoping problem that I am actually having, but his brief description of how to deal with it isn't enough for me to understand:

jq - How do I print a parent value of an object when I am already deep into the object's children?

I want to see this:

GroupName: "https"
GroupID: "sg-22222222"

I don't think I fully understand how using 'as' works, which may be my stumbling block.

Upvotes: 1

Views: 258

Answers (1)

oguz ismail
oguz ismail

Reputation: 50750

Don't descend into children if you need parent.

.SecurityGroups[]
| select(any(.IpPermissions[]; .FromPort == 22))
| .GroupName, .GroupId

should work.

Upvotes: 3

Related Questions