쉘 스크립트를 디버깅하려고 합니다.
content_type='-H "Content-Type: application/json"'
curl $content_type -d "{"test": "test"}" example.com
나는 이것이 내 기대에 부응하지 못한다는 것을 배웠습니다. 이 스크립트에서 curl
(때문에)에 전달된 매개변수는 $content_type
다음과 같습니다.
-H
"Content-Type:
application/json"
(내가 기대했던 것) 대신:
-H
Content-Type: application/json
나는 다음과 같은 스크립트를 작성할 수 있다는 것을 알고 있습니다.
content_type="Content-Type: application/json"
curl -H "$content_type" -d "{"test": "test"}" example.com
이런 식으로 작동하지만 단일 변수에 매개변수가 포함된 여러 공간을 저장할 수 있는지 알고 싶습니다.
두 번째(작동) 버전의 경우 콘텐츠 유형을 제외하려면 -H
및 2가지를 제거해야 합니다 $content_type
.
그러나 옵션과 해당 값을 단일 엔터티에 넣어 콘텐츠 유형을 제외/포함하면 단일 엔터티가 제거/추가되도록 하는 것이 가능한지 알고 싶습니다.
POSIX에는 배열이 없기 때문에 배열을 사용하는 것은 이식성이 없습니다.
첫 번째 방법이 왜 이렇게 작동합니까?
왜냐하면분사. 우리가 다음과 같이 정의할 때 content_type
:
content_type='-H "Content-Type: application/json"'
다음과 같은 값을 갖습니다.
-H "Content-Type: application/json"
따옴표 없이 변수를 인용하면(예: $content_type
대신 "$content_type"
) 확장된 값이 토큰화의 대상이 됩니다. ~에서단어 분할 페이지배쉬 매뉴얼:
쉘은 단어 분할을 위해 큰따옴표 안에 표시되지 않는 인수 확장, 명령 대체 및 산술 확장의 결과를 스캔합니다.
같은 페이지에서:
쉘은 각 문자를
$IFS
구분 기호로 처리하고 이러한 문자를 필드 종결자로 사용하여 다른 확장 결과를 단어로 분할합니다. IFS가 설정되지 않았거나 해당 값이 다음과 같은 경우<space><tab><newline>
...
따라서 -H "Content-Type: application/json"
이를 구분 기호로 사용하여 분리합니다. <space><tab><newline>
이는 우리에게 다음을 제공합니다.
-H
"Content-Type:
application/json"
답변1
가지다하나표준 쉘의 표준 배열과 유사한 구조입니다. 위치 매개변수입니다. 따라서 가능한 해결책은 set -- …
및 를 사용하는 것입니다 "$@"
. 귀하의 경우에는 다음을 수행합니다.
set -- -H "Content-Type: application/json"
curl "$@" -d "{"test": "test"}" example.com
이는 사용 가능한 어레이를 하나만으로 제한한다는 점에 유의하십시오. 예를 들어, 하나는 컬용으로 사용하고 다른 하나는 다른 프로그램용으로 사용할 수 없습니다. 물론 스크립트의 매개변수가 손상됩니다.
답변2
관련 부분 복사자일스의 대답:
명령을 변수에 저장하는 방법은 무엇입니까?
"명령"은 세 가지를 의미할 수 있습니다: 명령 이름(전체 경로가 있거나 없는 실행 파일의 이름, 내장 또는 별칭이 지정된 함수 이름), 매개변수가 있는 명령 이름 또는 셸 코드 조각 . 따라서 변수에 저장하는 방법에는 여러 가지가 있습니다.
명령 이름이 있으면 저장하고 평소처럼 큰따옴표가 포함된 변수를 사용하세요.
command_path="$1" … "$command_path" --option --message="hello world"
인수를 취하는 명령이 있는 경우 문제는 위의 파일 이름 목록과 동일합니다. 즉, 문자열이 아닌 문자열 목록입니다. 중간에 공백이 있는 문자열에는 매개변수를 채울 수 없습니다. 그렇게 하면 매개변수의 일부인 공백과 매개변수를 구분하는 공백 간의 차이를 알 수 없기 때문입니다. 쉘에 배열이 있으면 이를 사용할 수 있습니다.
cmd=(/path/to/executable --option --message="hello world" --) cmd=("${cmd[@]}" "$file1" "$file2") "${cmd[@]}"
사용 중인 셸에 배열이 없으면 어떻게 되나요? 위치 매개변수를 수정해도 괜찮다면 계속 사용할 수 있습니다.
set -- /path/to/executable --option --message="hello world" -- set -- "$@" "$file1" "$file2" "$@"
복잡한 셸 명령(예: 리디렉션, 파이프 등)을 저장해야 하는 경우 어떻게 해야 합니까? 아니면 위치 매개변수를 수정하고 싶지 않다면? 그런 다음 해당 명령이 포함된 문자열을 작성하고
eval
내장 명령을 사용할 수 있습니다.code='/path/to/executable --option --message="hello world" -- /path/to/file1 | grep "interesting stuff"' eval "$code"
누구든지 전체 기사를 읽어 보시기 바랍니다.자일스의 대답하지만. 여기에는 유용한 정보가 많이 포함되어 있습니다.