bash에서 여러 개의 중첩된 작은따옴표, 큰따옴표 및 따옴표 붙은 변수를 사용하여 명령을 실행하는 방법

bash에서 여러 개의 중첩된 작은따옴표, 큰따옴표 및 따옴표 붙은 변수를 사용하여 명령을 실행하는 방법

이것은 내 간단한 스크립트입니다.

#!/bin/sh
thefile=/home/ark/arkserver/ShooterGame/Saved/SaveIsland/1288804998.arktribe

while inotifywait "${thefile}" ; do
    a=\"`strings ${thefile} | tail -n 5 | head -n 1 | sed 's/<[^>]*>//g'`\"
echo $a

curl -H "Content-Type: application/json" -X POST -d '{\"username\": \"Island\", \"content\": $a}' https://discordapp.com/api/webhooks/5738674701/OjRQiAWHq5mX0Tn2MfBlF-mI41TWrVYVAbOfXpeZWqo8

done

이것이 출력이다

Setting up watches.
Watches established.
/home/ark/arkserver/ShooterGame/Saved/SaveIsland/1288804998.arktribe ATTRIB
"Day 600, 21:31:17: Phorce1 demolished a 'Campfire'!"
{"code": 50006, "message": "Cannot send an empty message"}Setting up watches.
Watches established.

컬 명령을 적절하게 인용하고 중간에 변수를 삽입하는 방법을 모르겠습니다. 명령은 다음과 같아야 합니다. 이는 명령줄에 입력할 때 작동합니다.

curl -H "Content-Type: application/json" -X POST -d '{"username": "test", "content": "Day 600, 14:51:00: Phorce1 demolished a 'Campfire'!"}' https://discordapp.com/api/webhooks/594723628738674701/OjRQn2MfBlF-FJVl1cWwMlD6UQf0c

나는 다양한 형태의 인용을 시도했습니다. 올바르게 인용된 $a를 에코하지만 이를 사용하여 명령에서 여전히 뭔가가 중단된다는 사실이 나를 혼란스럽게 합니다.

(예, 웹훅 주소를 깨뜨렸습니다)

이 질문은 중복된 것으로 표시되었습니다.또 다른 문제, 하지만 이 질문에 대한 대답은 단순히 따옴표를 이스케이프 처리하는 것입니다. 내 스크립트에 있는 컬 명령줄의 "중첩된 따옴표" 특성으로 인해 이러한 답변이 실패했습니다. 내 질문을 게시하기 전에 다양한 형태의 이스케이프 인용문을 시도했습니다. 다른 질문에 대한 답변에서 언급된 이스케이프된 따옴표를 사용하면 문제 없이 따옴표 안의 변수에 대한 간단한 "에코"를 얻을 수 있지만 "다른 따옴표 세트 내의 다른 따옴표 안에"를 삽입하면 컬 명령줄이 실패합니다. .

답변1

아포스트로피예방하다가변 확장.

나는 이렇게 할 것이다:

url=https://discordapp.com/api/webhooks/5738674701/OjRQiAWHq5mX0Tn2MfBlF-mI41TWrVYVAbOfXpeZWqo8
while inotifywait "$thefile" ; do
    a=$(strings "$thefile" | tail -n 5 | head -n 1 | sed 's/<[^>]*>//g')
    echo "$a"
    payload=$(printf '{"username": "Island", "content": "%s"}' "$a")
    curl -H "Content-Type: application/json" -X POST -d "$payload" "$url" 
done

작은따옴표 안에 큰따옴표를 이스케이프 처리할 필요는 없습니다. 실제로 이렇게 하면 이스케이프된 문자가 리터럴 문자로 보존됩니다.

변수를 인용하지 않으면 어떤 일이 일어날지 정확히 알지 않는 한 항상 변수를 인용하세요.

(개인 스타일의 문제입니다)필요주변 텍스트와 변수 이름을 명확하게 구분해야 하는 경우가 아니면 변수를 따옴표로 묶습니다.

echo "$aVariable"
echo "${aVariable}_abc"

답변2

사용자 제공 데이터가 포함된 JSON 문서를 생성하고 이를 올바르게 인코딩하려면 다음과 같은 방법을 사용하세요 jq.

payload=$( jq --arg content "$data" -n '{"username": "Island", "content": $content}' )

$payload그러면 키-값 필드의 값이 포함된 작은 JSON 문서가 생성됩니다 . 값은 올바르게 인용됩니다(큰따옴표 및 ASCII가 아닌 문자 등은 올바르게 처리됩니다).$datacontent

예를 들어, $data문자 그대로라면

"hello
world"

(따옴표 및 줄 바꿈 포함) 위 명령은 다음 JSON 문서를 생성하고 이를 tho payload변수에 할당합니다.

{
  "username": "Island",
  "content": "\"hello\nworld\""
}

생성된 문서에서 불필요한 공백을 제거하려면 jq해당 -c옵션을 사용하십시오.

전체 스크립트는 다음과 같습니다

#!/bin/sh

url='https://discordapp.com/api/webhooks/5738674701/OjRQiAWHq5mX0Tn2MfBlF-mI41TWrVYVAbOfXpeZWqo8'
file='/home/ark/arkserver/ShooterGame/Saved/SaveIsland/1288804998.arktribe'

while inotifywait "$file" ; do
    data=$( strings "$file" | tail -n 5 | head -n 1 | sed 's/<[^>]*>//g' )
    payload=$( jq --arg content "$data" -n '{"username": "Island", "content": $content}' )

    curl -H "Content-Type: application/json" \
         -X POST \
         -d "$payload" \
         "$url"
done

걱정해야 할 유일한 것은 쉘 변수를 인용하는 것입니다. 이 변수는 큰따옴표로 묶어야 합니다.평소처럼. 파이프에서 읽은 데이터에 리터럴 따옴표를 삽입하려고 할 필요가 없습니다.

관련 정보