4

Given json:

[
  {
    "path": "Module1/",
    "users": [
      "john",
      "jane"
    ]
  },
  {
    "path": "Module2/",
    "users": [
      "mike",
      "mary"
    ]
  },
  {
    "path": "Module3/",
    "users": [
      "billy",
      "bonny"
    ]
  }
]

Given array of files:

[
  "Module1/file.java",
  "Module3/file.java"
]

How can I get the users for which any of the files match the path?

Expected output:

[
  "john",
  "jane",
  "billy",
  "bonny"
]

I recently found this answer to a similar question, which cleverly builds regex filter and passes as arg in jq: https://stackoverflow.com/a/54630000/8784215

I set up similarly:

users='[{"path":"Module1/","users":["john","jane"]},{"path":"Module2/","users":["mike","mary"]},{"path":"Module3/","users":["billy","bonny"]}]'
files='["Module1/file.java","Module3/file.java"]'
filter=($(echo $files | jq -r  '. | join(" ")'))
echo $users | jq --arg re "$(IFS="|"; echo "${filter[*]}")" '[.[] | select(.path | test($re)) | .users[]]'

But the problem is that path is being matched against file, when it should be the other way around.

Any ideas?

Cody
  • 137
  • 5

1 Answers1

5

You can use ìnside to flip arguments for a contains test which performs a substring matching. Use any to select on first match, and input to read the second input (array of files):

jq 'input as $f | map(select(any(.path | inside($f[]); .)).users[])' input.json files.json
[
  "john",
  "jane",
  "billy",
  "bonny"
]

Demo

pmf
  • 24,478
  • 2
  • 22
  • 31