2

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?

peak
  • 105,803
  • 17
  • 152
  • 177
tomsoft
  • 4,448
  • 5
  • 28
  • 35

1 Answers1

4

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

peak
  • 105,803
  • 17
  • 152
  • 177
  • 1
    I think the admonition against using `--argfile` is overreaching. It's makes perfect sense to use `--argfile` when the input is a JSON file as is the case here. Don't use it when the file is a sequence of JSON texts, and you're fine. tl;dr: `--argfile` for JSON text. `--slurpfile` for JSON texts. – ikegami Mar 26 '21 at 19:18
  • @ikegami - I agree but for those who may not know, there is a reason why it has been deprecated: it sometimes behaves like --slurpfile. Perhaps in future it will ignore all but the first JSON entity .... – peak Mar 26 '21 at 20:18