curl
x-www-form-urlencode 를 사용하여 파일 내에서 POST JSON 데이터를 실행 하려고 합니다 docker-compose
. 이 예에서는 이 공개 웹사이트를 사용하고 있으며 다음과 같이 응답해야 합니다.
# sh -c 'curl http://httpbin.org/post -F "json={\"key\": \"value\"}"'
{
"args": {},
"data": "",
"files": {},
"form": {
"json": "{\"key\": \"value\"}"
}, ...
이것은 외부의 작은 따옴표로 잘 작동하지만 내부에 변수가 있기 때문에 큰 따옴표가 필요합니다. 따라서 이 명령은 작동하지 않으며 중첩된 따옴표를 이스케이프 처리하는 올바른 구문을 알아낼 수 없습니다.
# sh -c "curl http://httpbin.org/post -F "json={\"key\": \"$VAR\"}""
{
"args": {},
"data": "",
"files": {},
"form": {
"json": "{key:"
},
답변1
전송되는 매개변수에 삽입하려는 데이터 curl
는 JSON 문서를 인코딩하는 JSON 인코딩 문자열입니다.
문자열은 다음과 같이 별도로 생성할 수 있습니다.
json_string=$( jq -n --arg 'my key' 'my "value"' '$ARGS.named|@json' )
JSON 인식 도구를 사용하여 jq
데이터를 JSON 인코딩 문자열로 변환함으로써 문자열의 내용이 유효한 JSON 문자열이고 my key
지정된 키, 및 를 포함하는 유효한 JSON 문서로 디코딩될 수 있는지 확인합니다. 값, my "value"
.
위의 정확한 명령은 문자열을 "{\"my key\":\"my \\\"value\\\"\"}"
에 할당합니다 json_string
.
curl
그런 다음 아래와 같이 매개변수에서 이 문자열을 사용하여 직접 호출 할 수 있습니다 .
curl 'http://httpbin.org/post' -F "json=$json_string"
sh -c
...또는 아래와 같이 문자열을 해당 스크립트에 매개변수로 전달하여 인라인 스크립트에서 호출할 수 있습니다.
sh -c 'curl "http://httpbin.org/post" -F "json=$1"' sh "$json_string"
이러한 호출 중 하나는 curl
다음과 같은 응답을 가져옵니다.
{
"args": {},
"data": "",
"files": {},
"form": {
"json": "{\"my key\":\"my \\\"value\\\"\"}"
},
"headers": {
"Accept": "*/*",
"Content-Length": "160",
"Content-Type": "multipart/form-data; boundary=------------------------f805cf070f665e7e",
"Host": "httpbin.org",
"User-Agent": "curl/7.84.0",
"X-Amzn-Trace-Id": "Root=1-83012651-2995681c270059da2906c40f"
},
"json": null,
"origin": "xxx.xxx.xxx.xxx",
"url": "http://httpbin.org/post"
}
JSON 문서를 JSON 문자열로 인코딩하는 것은 curl
자체적으로 수행되는 것처럼 보이기 때문에 꼭 필요한 것은 아닙니다.
json_string=$( jq -n -c --arg 'my key' 'my "value"' '$ARGS.named' )
jo
...JSON 문자열을 생성하거나, 설치 한 경우 더 짧은 문자열을 생성합니다.
json_string=$( jo 'my key'='my "value"' )
답변2
이와 같이?
$ var=hello
$ sh -c "curl http://httpbin.org/post -F 'json={\"key\": \"$var\"}'"
{
"args": {},
"data": "",
"files": {},
"form": {
"json": "{\"key\": \"hello\"}"
},
메모:
$ sh -c "curl http://httpbin.org/post -F 'json={\"key\": \"$var\"}'"
1 2 3 3 34 3 21
(1) 바깥쪽 큰따옴표, (2) 작은따옴표,아니요내부 큰따옴표는 특별하므로 이스케이프할 필요가 없습니다. (3) 내부 큰따옴표는 외부 큰따옴표에 대해 이스케이프됩니다. (4) 실행하기 전에 외부 큰따옴표 안에 변수 확장을 수행합니다 sh -c
(변수 값 안에 작은따옴표가 있으면 내부 셸에 문제가 발생하고 거기에 있는 큰따옴표가 JSON 구문을 엉망으로 만들 수 있다는 점에 유의하세요).
sh
Bash이고 를 사용하여 실행하면 다음 -x
과 같이 실행되는 것을 볼 수 있습니다.
+ curl http://httpbin.org/post -F 'json={"key": "hello"}'
2 3 3 3 3 2
이는 보이는 것과 거의 동일합니다 sh -c
. 여기서 (2)는 인용된 문자열이고 (3)은 문자열에서 특수하지 않은 큰따옴표입니다.
(Dash의 출력이 명시적이지 않기 때문에 "Bash에서"라고 말합니다 set -x
. Bash에서는 일반적으로 -x
인용된 출력을 다시 실행합니다. 예를 들어 명령을 내리면 echo "foo bar"
로 표시됩니다 echo 'foo bar'
. 그러나 이것은 실제로 특별한 경우를 변경하지는 않습니다. ).
답변3
Heredocs를 사용하면 이 인용문을 더 쉽게 관리할 수 있습니다.
sh <<END_SCRIPT
curl http://httpbin.org/post -F 'json={"key": "$VAR"}'
END_SCRIPT
Heredoc 자체는 참조되지 않으므로 변수가 대체됩니다.
만약 VAR="foo bar"
, 우리는 얻는다
...
"form": {
"json": "{\"key\": \"foo bar\"}"
},
...
걱정해야 할 유일한 것은 변수 값에 따옴표가 포함되어 있는지 여부입니다.
VAR='She said "Hello"'
잘못된 JSON이 표시됩니다 .
...
"form": {
"json": "{\"key\": \"She said \"Hello\"\"}"
},
...
쉘 매개변수 확장을 사용하여 내부 따옴표를 이스케이프 처리할 수 있습니다.
sh <<END_SCRIPT
curl http://httpbin.org/post -F 'json={"key": "${VAR//\"/\\\"}"}'
END_SCRIPT
~하도록 하다
...
"form": {
"json": "{\"key\": \"She said \\\"Hello\\\"\"}"
},
...