Use jq to retrieve fields specified on command line

Given this input

{
  "attributes": {
    "f1": "one",
    "f2": "two",
    "f3": "three"
  }
}

I’d like to be able to specify on the jq command line which fields to retrieve and spit their values out space-delimited on the same line.

jq -r 'some-filter' --argjson fields '["f3","f1"]' test.json

Result: three one

jq -r 'some-filter' --argjson fields '["f2"]' test.json

Result: two

I’ve tried several variations of this filter, with no luck

.attributes
 | $fields | . as $f | "($f)"
Asked By: SteveT

||

You could do it using variable-symbolic binding (as you attempted) as

jq -r --argjson fields '["f3","f1"]' '[$fields[] as $f | .attributes | .[$f]] | join(" ")' test.json

or slightly more compactly

jq -r --argjson fields '["f3","f1"]' '[$fields[] as $f | .attributes[$f]] | join(" ")' test.json

but at least with jq 1.6 it seems you can just pass the $fields[] iterator to a generic object index of the form .[<string>]

jq -r --argjson fields '["f3","f1"]' '[.attributes[$fields[]]] | join(" ")' test.json

ex.

$ jq -r --argjson fields '["f3","f1"]' '[.attributes[$fields[]]] | join(" ")' test.json
three one
$ jq -r --argjson fields '["f2"]' '[.attributes[$fields[]]] | join(" ")' test.json
two
Answered By: steeldriver

If you really want to pass in a JSON array with the keys whose values you want to extract, you could do that like so

jq -r --argjson keys '["f3", "f1"]' '.attributes[$keys[]]' file.json

Given the data in the question, this would return

three
one

To get these on the same line with a space delimiter:

jq -r --argjson keys '["f3", "f1"]' '[.attributes[$keys[]]] | join(" ")' file.json

or, by simply passing the output of the first command to paste -d ' ' -s -:

jq -r --argjson keys '["f3", "f1"]' '.attributes[$keys[]]' file.json |
paste -d ' ' -s -

It would be more convenient for the user of the command to be able to mention the fields they want without having to create a JSON array (potentially having to remember to encode the keys properly):

jq -r '.attributes[$ARGS.positional[]]' file.json --args f3 f1

Or, for the space-delimited single-line output variant:

jq -r '.attributes[$ARGS.positional[]]' file.json --args f3 f1 |
paste -d ' ' -s -

Note that --args and the subsequent arguments need to be last on the command line.

Answered By: Kusalananda
Categories: Answers Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.