Home > database >  Using BASH and JQ I want to compare a json file against a bash array
Using BASH and JQ I want to compare a json file against a bash array

Time:07-27

Example:

BASH ARRAY FRUITS=("APPLE" "BANANA" "ORANGE")

fruit.json

{
    "fruit": [
        "apple", 
        "orange",
        "pomegranate",
        "apricot",
        "mango"
    ]
}

What I need to do:

  1. Compare Bash fruit array against fruit.json file and output if it matches all the elements.
  2. If the fruit.json file is missing a fruit element from the bash array I have to display which one it is.
  3. If the fruit.json file has any extra fruit elements that are not in the bash array I have to output it.

I managed to figure out the first two tasks but I am having trouble with the third. Any ideas on how to achieve the third using bash and jq?

CodePudding user response:

Use comm to compare two lists.

comm \
  <(jq < fruit.json -r '.fruit | sort | .[] | ascii_upcase ') \
  <(printf "%s\n" "${FRUITS[@]}" | sort)

will output a three-column list: elements only in fruit.json, elements only in FRUITS, and common elements. To supress a column, use the appropriate options to comm: -23 will suppress the second and third column, giving you just the fruit.json-only elements. Similarly, -13 will provide just the FRUITS-only elements.

CodePudding user response:

Here is a "pure jq" solution to Part 3 except that it uses printf to facilitate the importing of the bash array:

printf '%s\n' "${FRUITS[@]}" | 
  jq -nRr --argfile fruit <(json) '($fruit.fruit | map(ascii_upcase)) - [inputs] | .[]'

This assumes that the strings in FRUITS are already uppercased, but does not assume they are sorted.

Note also that the semantics of jq's - applied to arrays is quite different from the semantics of comm, notably w.r.t. the handling of duplicates.

CodePudding user response:

This response addresses the task for which help is requested:

If the fruit.json file has any extra fruit elements that are not in the bash array I have to output it.

The following will output the uppercase strings corresponding to those elements in .fruit that do not appear in the bash array, assuming the entries in the latter are all uppercase:

comm -23 <(< fruit.json jq -r '.fruit | map(ascii_upcase) | sort[]') <(printf '%s\n' "${FRUITS[@]}" | sort )

This uses the standard command-line utilities comm, sort, and printf. A "pure jq" solution would also be straightforward except perhaps for the importing of the elements of the bash array into jq.

  • Related