having an input like this:
[
{
"foo": "aaa",
"bar": 111
},
{
"foo": "bbb",
"bar": 111
},
{
"foo": "ccc",
"bar": 222
},
{
"foo": "aaa",
"bar": 333
},
{
"foo": "ddd",
"bar": 444
}
]
i would like to select all objects with "foo" key equal to "aaa" or "bbb". so the solution is obvious:
.[] | select (.foo=="aaa" or.foo=="bbb" )
.[] | select (.foo=="aaa" or.foo=="bbb" )
( https://jqplay.org/s/x7FGo1uQNW )
but i would like to enhance it and replace that x=y or x=z
to sql'ish styled x in (y,z)
. and i got stuck, as the natural try:
.[] | select (.foo in (["aaa", "bbb"]) )
results in an error:
jq: error: syntax error, unexpected IDENT, expecting ';' or ')' (Unix shell quoting issues?) at, line 1:
i also tried this:
.[] | select (.foo | in (["aaa", "bbb"]) )
but also not great...
jq: error (at:21): Cannot check whether array has a string key
is this even posible?
hmm, i managed to do it with this:
.[] | select(.foo as $tmpvar | ["aaa", "bbb"] | index ($tmpvar ) )
https://jqplay.org/s/g7AyRgARdU
According to this answer: https://stackoverflow.com/a/46470951/2244766 in versions above 1.5 there is a new IN
operator that makes life a bit easier:
.[] | select(.foo|IN("aaa","bbb"))
The SQL-style operators don't work well for me as a straight-forward selection mechanism; I believe they have a very specific use-case, for which they are uniquely suitable for, and for anything else they're (at best) clunky. At least that's been my experience. And I haven't really figured out what that specific use-case is, either.
With all of that as a backdrop, my recommendation is to use a simple regex test:
map(select(.foo | test("aaa|bbb")))
Given the example JSON:
<~> $ jq . /tmp/so4229.json
[
{
"foo": "aaa",
"bar": 111
},
{
"foo": "bbb",
"bar": 111
},
{
"foo": "ccc",
"bar": 222
},
{
"foo": "aaa",
"bar": 333
},
{
"foo": "ddd",
"bar": 444
}
]
the above filter would result in:
<~> $ jq 'map(select(.foo | test("aaa|bbb")))' /tmp/so4229.json
[
{
"foo": "aaa",
"bar": 111
},
{
"foo": "bbb",
"bar": 111
},
{
"foo": "aaa",
"bar": 333
}
]
If you need to generate the regex based on other data within the JSON, you can do that, too:
. as $data | map(select(.bar==111) | .foo) | join("|") as $regex | . = $data | map(select(.foo | test($regex)))
which would result in:
<~> $ jq '. as $data | map(select(.bar==111) | .foo) | join("|") as $regex | . = $data | map(select(.foo | test($regex)))' /tmp/so4229.json
[
{
"foo": "aaa",
"bar": 111
},
{
"foo": "bbb",
"bar": 111
},
{
"foo": "aaa",
"bar": 333
}
]
There may be a better way to run through the JSON twice (once to get the regex values, once to use it).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.