Filter in jq based on an array of string

Viewed 456

This is close to this question: jq filter JSON array based on value in list , the only difference being the condition. I don't want equality as a condition, but a "contains", but I am struggling to do it correctly.

The problem: If want to filter elements of an input file based on the presence of a specific value in an entry The input file:

[{
    "id":"type 1 is great"
},{
    "id":"type 2"
},
{
    "id":"this is another type 2"
},
{
    "id":"type 4"
}]

The filter file: ids.txt:

type 2
type 1

The select.jq file:

 def isin($a): . as $in | any($a[]; contains($in));
 map( select( .id | contains($ids) ) )

The jq command:

jq --argjson ids "$(jq -R . ids.txt | jq -s .)" -f select.jq test.json

The expected result should be something like:

[{
  "id":"type 1 is great"
},{
 "id":"type 2"
},
{
  "id":"this is another type 2" 
}]

The problem is obviously in the "isin" function of the select.jq file, so how to write it correctly to check if an entry contains one of the string of another array?

1 Answers

Here is a solution that illustrates that there is no need to invoke jq more than once. In accordance with the jq program shown in the question, it also assumes that the selection is to be based on the values of the "id" key.

< ids.txt jq -nR --argfile json input.json '
  # Is the input an acceptable value?
  def acceptable($array): any(contains($array[]); .);

  [inputs] as $substrings
  | $json 
  | map( select(.id | acceptable($substrings)) )
'

Note on --argfile

--argfile has been deprecated, so you may wish to use --slurpfile instead, in which case you'd have to write $json[0].

Related