1

I got the JSON string below I use to feed to aws route53 change-resource-record-sets command to update a current DMARC record. As you can see the TXT value contains ;.

JSON="{ \"Comment\": \"Updating TXT record in $domain\", 
  \"Changes\": [ { \"Action\": \"UPSERT\", \"ResourceRecordSet\": { \"Name\": 
  \"_dmarc.${domainName}\", \"Type\": \"TXT\", \"TTL\": 
  3600, \"ResourceRecords\": [ { \"Value\": "\"v=DMARC1\; p=reject\; pct=100\"" } ] } } ] }"

When I echo $JSON, instead of the whole JSON string, I got the below output. It appears the parse stops as soon as it hit ;.

{ "Comment": "Updating TXT record in ", 
  "Changes": [ { "Action": "UPSERT", "ResourceRecordSet": { "Name": 
  "_dmarc.contoso.com", "Type": "TXT", "TTL": 
  3600, "ResourceRecords": [ { "Value": "v=DMARC1;

I have tried number of ways to escape the semicolon, like using \\; and \";\" without luck. What did I do wrong here?

2
  • 1
    The site colorizes code. If one notices the fragment containing p=reject is black, if one asks oneself why it's not green like other quoted strings, then one will discover it's not really quoted. Is not-quoting by design? Your answer adds escaping to the unquoted fragment, while the obvious solution (obvious after noticing the fragment is unquoted) is not to close the quoting prematurely. This makes me suspect that maybe you think you needed to escape spaces inside a quoted string for some mysterious reason. This belief will confuse you sooner or later. You have escaped unquoted spaces. Oct 24 '21 at 23:56
  • At this place you put unescaped extra doublequites before DMARC1 and after pct=100: ``` \"Value\": "\"v=DMARC1\; p=reject\; pct=100\"" } ```
    – Saboteur
    Oct 25 '21 at 6:52
1

Just use a mix of single and double quotes and then it will not look so messy and will be easier to work with:

JSON='{ "Comment": "Updating TXT record in $domain", 
  "Changes": [ { "Action": "UPSERT", "ResourceRecordSet": { "Name": 
  "_dmarc.${domainName}", "Type": "TXT", "TTL":  
  3600, "ResourceRecords": [ { "Value": "v=DMARC1; p=reject; pct=100" } ] } } ] }'

This one works. Example:

$ JSON='{ "Comment": "Updating TXT record in $domain",
  "Changes": [ { "Action": "UPSERT", "ResourceRecordSet": { "Name":
  "_dmarc.${domainName}", "Type": "TXT", "TTL":
  3600, "ResourceRecords": [ { "Value": "v=DMARC1; p=reject; pct=100" } ] } } ] }'
$
$ echo $JSON | jq .
{
  "Comment": "Updating TXT record in $domain",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "_dmarc.${domainName}",
        "Type": "TXT",
        "TTL": 3600,
        "ResourceRecords": [
          {
            "Value": "v=DMARC1; p=reject; pct=100"
          }
        ]
      }
    }
  ]
}
$
1
  • You missed the fact that the user probably used double quotes to be able to insert the values from two shell variables. You also deleted data from the last string in the document without comment.
    – they
    Oct 25 '21 at 13:41
0

Turns out the issue here is not escaping the semicolons, but the trailing space after the semicolon. After I changed the string to something like this

{ \"Value\": "\"v=DMARC1\;\ p=reject\;\ pct=100\"" }

The string is now echo properly!

{ "Value": "v=DMARC1; p=reject; pct=100" }
1
  • No, you forgot to escape the double quote after the first colon. You then additionally failed to escape the backslashes.
    – they
    Oct 25 '21 at 13:42
0

You are lacking escapes on a few quotes and backslashes at the end. It would be easier to manage the quoting if you use single quotes around the JSON document string.

It seems as if you want to insert values from shell variable into a JSON document. You do that safest with jq:

$ domain=my.domain.example.com
$ domainName=some-domain-name
$ JSON=$( jq -c -n --arg domain "$domain" --arg name "$domainName" '
{ "Comment": "Updating TXT record in \($domain)",
  "Changes": [ {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "_dmarc.\($name)", "Type": "TXT", "TTL": 3600,
        "ResourceRecords": [ { "Value": "\"v=DMARC1; p=reject; pct=100\"" } ]
      } } ] }' )

The jq command is used here to insert the values of the two shell variables domain and domainName into an in-line JSON document. The two variables are used on the command line to initialize two internal jq variables, $domain and $name, respectively. These are referenced by the JSON document, in the strings where they are supposed to be inserted.

Doing it this way ensures that any characters that need special escaping are properly escaped for inclusion into the JSON strings in the document.

Note that I've left the embedded double quotes in that string at the end, as I don't know if they are required or not. A JSON parser would properly decode the escaped quotes when it's reading the data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.