Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq: select where .attribute in list

In python I can do:

>>> 5 in [2,4,6]
False
>>> 5 in [4,5,6]
True

to determine if the give value 5 exists in the list. I want to do the same concept in jq. But, there is no in. Here is an example with a more realistic data set, and how I can check for 2 values. In my real need I have to check for a few hundred and don't want to have all those ored together.

jq '.[] | select(.PrivateIpAddress == "172.31.6.209"
                 or
                 .PrivateIpAddress == "172.31.6.229")
        | .PrivateDnsName' <<EOF
[
    {
        "PrivateDnsName": "ip-172-31-6-209.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.209"
    },
    {
        "PrivateDnsName": "ip-172-31-6-219.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.219"
    },
    {
        "PrivateDnsName": "ip-172-31-6-229.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.229"
    },
    {
        "PrivateDnsName": "ip-172-31-6-239.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.239"
    }
]
EOF
like image 490
Bruno Bronosky Avatar asked Jun 07 '18 21:06

Bruno Bronosky


People also ask

Which selector selects each element with the specified attribute and value?

The [attribute=value] selector selects each element with the specified attribute and value. Required. Specifies the attribute to find Required. Specifies the value to find

How do I check membership in an array using JQ?

If your jq does not have it, you can use this definition for IN/1: If you want to check membership in an array, say $a, simply use IN ( $a [] ). It's Peter Koppstein!

What is an example of a selector in jQuery?

jQuery Selectors Selector Example Selects * $ ("*") All elements # id $ ("#lastname") The element with id="lastname" . class $ (".intro") All elements with class="intro" . class,. class $ (".intro,.demo") All elements with the class "intro" or " ... 26 more rows ...

How do I iterate over an array in JQ?

As with many programming languages, jq uses square brackets to indicate the beginning and end of an array. The following example shows how to iterate over an array. In case the array is containing objects, you can extract properties from each object in the array by chaining commands.


2 Answers

using ,

I don't know where in https://stedolan.github.io/jq/manual/v1.5/ this is documented. But the answer is in that jq does implicit one-to-many and many-to-one munging.

jq '.[] | select(.PrivateIpAddress == ("172.31.6.209",
                                       "172.31.6.229"))
        | .PrivateDnsName' <<EOF
[
    {
        "PrivateDnsName": "ip-172-31-6-209.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.209"
    },
    {
        "PrivateDnsName": "ip-172-31-6-219.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.219"
    },
    {
        "PrivateDnsName": "ip-172-31-6-229.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.229"
    },
    {
        "PrivateDnsName": "ip-172-31-6-239.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.239"
    }
]
EOF

(the formatting/indenting of code was made to match that of the OP to simplify visual comparison)

The output is:

"ip-172-31-6-209.us-west-2.compute.internal"
"ip-172-31-6-229.us-west-2.compute.internal"

"Seems like voodoo to me."

using | IN("a","b","c")

Update: It's been 16 months, and I've finally learned how to use the IN function. Here is a demo that will produce the same results as above.

cat > filter.jq <<EOF
# Either of these work in jq < v1.5, but I've commented them out since I'm using v1.6
# def IN(s): first( if (s == .) then true else empty end ) // false;
# def IN(s): first(select(s == .)) // false;

.[] | select(.PrivateIpAddress | IN("172.31.6.209","172.31.6.229")) | .PrivateDnsName
EOF

jq -f filter.jq <<EOF
[
    {
        "PrivateDnsName": "ip-172-31-6-209.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.209"
    },
    {
        "PrivateDnsName": "ip-172-31-6-219.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.219"
    },
    {
        "PrivateDnsName": "ip-172-31-6-229.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.229"
    },
    {
        "PrivateDnsName": "ip-172-31-6-239.us-west-2.compute.internal",
        "PrivateIpAddress": "172.31.6.239"
    }
]
EOF
like image 59
Bruno Bronosky Avatar answered Oct 22 '22 10:10

Bruno Bronosky


But, there is no in.

You could use index/1, as documented in the manual. Even better would be to use IN, which however was only introduced after the release of jq 1.5. If your jq does not have it, you can use this definition for IN/1:

# return true or false as . is in the stream s
def IN(s):
  first( if (s == .) then true else empty end ) // false;

If you want to check membership in an array, say $a, simply use IN( $a[] ).

like image 38
peak Avatar answered Oct 22 '22 10:10

peak