1

I have a BASH Array as follows:

TEMPARRAY=( "1 A" "2 B" )

I want this array to convert to JSON Array (or Key Value Pair ?), like this:

{
  "Comment": "MX Record for XYZ",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "XYZ",
        "Type": "MX",
        "TTL": 300,
        "ResourceRecords": [
        {
          "Value": "1 A"
        },
        {
          "Value": "2 B"
        }
       ]
      }
    }
  ]
}

USE CASE: I am creating a shell script to add AWS Route53 DNS Records and I am stuck at specifying multiple values for MX records. If I update the MX records, it get replaced with a newer one.

Sample Code from my script:

      if [[ "$MXCOUNT" -gt "1" ]]; then
        TEMPARRAY=( "$(grep -i MX  "$DNSFILE" | cut -d, -f3)" )
        for i in "${TEMPARRAY[@]}"; do
         # POSSIBLE CODE HERE
        done
      else
        addMXrecord  "$DNSNAME" "$DNSVALUE"
      fi

The function addMXrecord will be containing the JSON (although it's for a single MX record.)

DNSFILE is in format:

DOMAIN,MX,1 A
DOMAIN,MX,2 B

Happy to provide anymore information.

4
  • 1
    There's more content in your proposed output file than there is in your input file. One can't very well manufacture data out of nothing. Commented Jun 12, 2017 at 16:15
  • 1
    ...that said, the general-purpose tool for this kind of operation (the accepted toolkit for JSON operations in shell, much as awk is for manipulation of line- and field-oriented files) is jq. Commented Jun 12, 2017 at 16:16
  • 1
    BTW, an answer to the literal question from the title (before getting into the weeds with question-specific details) looks like this: jq -cRn '[inputs]' < <( (( ${#array[@]} )) && printf '%s\n' "${array[@]}") Commented Jun 12, 2017 at 16:21
  • ...that said, since you want to parse a bunch of details out of your input, getting into the weeds would be necessary for a proper answer, and I don't have the time right now. Commented Jun 12, 2017 at 16:22

2 Answers 2

2

A jq filter for this would look like

TEMPARRAY=( "1 A" "2 B" )
printf '%s\n' "${TEMPARRAY[@]}" |
  jq --slurp -R '
    split("\n")[:-1] | map({Value: .}) |
    {
      Comment: "MX Record for XYZ",
      Changes: [
        {
          Action: "CREATE",
          ResourceRecordSet: {
            Name: "XYZ",
            Type: "MX",
            TTL: 300,
            ResourceRecords: .
          }
        }
      ]
    }
  '

split takes input lines and creates an array ["1 A", "2 B", ""] (the [:-1] gets rid of the final empty element due to the trailing newline from the input). map produces a corresponding array of objects [{"Value": "1 A"}, {"Value": "2 B"}]. The rest is just the template into which this array is inserted, as the value (represented by ., the input from map) to associate with the key ResourceRecords.

Sign up to request clarification or add additional context in comments.

Comments

0

This doesn't sound like something you'd want to implement in Bash, to be honest!

Either way, if you already have most of your script implemented in Bash, you could use a tool like jq, or if you don't want the additional dependency, you could "shell out" to, for instance, Python:

python -c 'import json, sys; print(json.dumps([{"Value": v} for v in sys.argv[1:]]))' foo bar

will output

[{"Value": "foo"}, {"Value": "bar"}]

which you can embed elsewhere.

2 Comments

This is the output I am looking for, and can replace this in the script. However, I tried with jq and no luck so far (even googled for syntax). Any help for this in bash ?
your python command works, will have to work with this as of now, until I figure something in BASH. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.