jq: select where .attribute in list
Asked Answered
G

2

17

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
Grating answered 7/6, 2018 at 21:55 Comment(0)
G
15

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
Grating answered 7/6, 2018 at 21:59 Comment(2)
Thanks to @pkoppstein for the help with this one! github.com/stedolan/jq/issues/370#issuecomment-395577269Grating
jq 1.6, if $key==("first","second") then.. effectively only checks for equality with "second". IN() works as expectedTarim
V
2

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[] ).

Vibraculum answered 7/6, 2018 at 22:4 Comment(2)
It's Peter Koppstein! I hit the <kbd>Run</kbd> button on stedolan.github.io/jq/manual/#ConditionalsandComparisons and did the "Value Iterator equal to group" test and was surprised by the result. jqplay.org/s/b2g7Rkiq0G I see what it's doing. But where is the why documented?Grating
In the official documentation, see "Comma: ,". If you have time, let me know what you think of this: docs.google.com/document/d/…Vibraculum

© 2022 - 2024 — McMap. All rights reserved.