Как экранировать точку с запятой в строке с помощью Bash

Как экранировать точку с запятой в строке с помощью Bash

Я получил строку JSON ниже, которую я использую для передачи aws route53 change-resource-record-setsкоманде для обновления текущей записи DMARC. Как вы можете видеть, значение TXT содержит ;.

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вместо всей строки JSON получил следующий вывод. Похоже, что парсинг останавливается, как только он достигает ;.

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

Я пробовал множество способов избежать точки с запятой, например, используя \\;и, но \";\"безуспешно. Что я сделал не так?

решение1

Просто используйте сочетание одинарных и двойных кавычек, и тогда код не будет выглядеть таким запутанным и с ним будет легче работать:

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" } ] } } ] }'

Это работает. Пример:

$ 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"
          }
        ]
      }
    }
  ]
}
$

решение2

Оказывается, проблема здесь не в экранировании точек с запятой, а в концевом пробеле после точки с запятой. После того, как я изменил строку на что-то вроде этого

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

Строка теперь воспроизводится правильно!

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

решение3

Вам не хватает экранирования в нескольких кавычках и обратных косых черт в конце. Было бы проще управлять кавычками, если бы вы использовали одинарные кавычки вокруг строки документа JSON.

Похоже, что вы хотите вставить значения из переменной оболочки в документ JSON. Безопаснее всего это сделать с помощью 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\"" } ]
      } } ] }' )

Команда jqиспользуется здесь для вставки значений двух переменных оболочки domainи domainNameв встроенный документ JSON. Две переменные используются в командной строке для инициализации двух внутренних jqпеременных $domainи $nameсоответственно. На них ссылается документ JSON в строках, куда они должны быть вставлены.

Такой подход гарантирует, что любые символы, требующие специального экранирования, будут правильно экранированы для включения в строки JSON в документе.

Обратите внимание, что я оставил встроенные двойные кавычки в этой строке в конце, так как не знаю, требуются ли они или нет. Парсер JSON правильно декодирует экранированные кавычки при чтении данных.

Связанный контент