Bash를 사용하여 문자열에서 세미콜론을 어떻게 이스케이프합니까?

Bash를 사용하여 문자열에서 세미콜론을 어떻게 이스케이프합니까?

aws route53 change-resource-record-sets현재 DMARC 레코드를 업데이트하는 명령 에 피드하는 데 사용하는 JSON 문자열이 아래에 있습니다 . 보시다시피 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은 두 개의 셸 변수 값을 인라인 JSON 문서에 삽입 domain하는 데 사용됩니다. domainName두 변수는 명령줄에서 각각 두 내부 jq변수 $domain및 를 초기화하는 데 사용됩니다. $name이는 삽입되어야 하는 문자열에서 JSON 문서에 의해 참조됩니다.

이렇게 하면 특수 이스케이프가 필요한 모든 문자가 문서의 JSON 문자열에 포함되도록 올바르게 이스케이프됩니다.

필수인지 아닌지 알 수 없으므로 해당 문자열 끝에 큰따옴표를 포함해 두었습니다. JSON 파서는 데이터를 읽을 때 이스케이프된 따옴표를 적절하게 디코딩합니다.

관련 정보