Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq: select when any value is in array

Given the input json

[
  {"title": "first line"},
  {"title": "second line"},
  {"title": "third line"}
]

How can we extract only the titles that contain keywords that are listed in a second "filter" array. Using a shell variable here for instance:

filter='["second", "third"]'

The output in this case would be

[
  {"title": "second line"},
  {"title": "third line"}
]

Also, how to use the array filter to negate instead. Eg: return only the "first line" entry in the previous example.

There is a similar reply but using an old version of jq. I hope that there's a more intuitive/readable way to do this with the current version of jq.

like image 376
Bernard Avatar asked Feb 11 '19 10:02

Bernard


People also ask

How do you filter jq?

jQuery filter() MethodThe filter() method returns elements that match a certain criteria. This method lets you specify a criteria. Elements that do not match the criteria are removed from the selection, and those that match will be returned.

How do you count arrays in jq?

The JQuery array length property sets or returns the length of the array. Suppose we have an array of numbers as “no = [ 51, 20, 64, 89, 45, 25 ]”, now we need to get the length of a no array. So we can use the array length property as “var len = no.

What is jq slurp?

“Slurp” tells jq to read every line of the input JSON lines and treat the entire group as one huge array of objects. With the Twitter data still in the input box on jq play, check the “Slurp” box, and just put .

Does jq have a function?

jQuery has() Method The has() method returns all elements that have one or more elements inside of them, that matches the specified selector. Tip: To select elements that have multiple elements inside of them, use comma (see example below).


1 Answers

You can use a combination of jq and shell tricks using arrays to produce the filter. Firstly to produce the shell array, use an array notation from the shell as below. Note that the below notation of bash arrays will not take , as a separator in its definition. Now we need to produce a regex filter to match the string, so we produce an alternation operator

filter=("first" "second")
echo "$(IFS="|"; echo "${filter[*]}"
first|second

You haven't mentioned if the string only matches in the first or last or could be anywhere in the .title section. The below regex matches for the string anywhere in the string.

Now we want to use this filter in the jq to match against the .title string as below. Notice the use of not to negate the result. To provide the actual match, remove the part |not.

jq --arg re "$(IFS="|"; echo "${filter[*]}")" '[.[] | select(.title|test($re)|not)]' < json
like image 75
Inian Avatar answered Sep 22 '22 21:09

Inian