이것은 터미널에서 직접 실행되지만 잘 작동합니다.
zenity --info --text "pure info" --title "get info"
그런데 이 스크립트가 작동하지 않습니다. 무슨 일이 일어나고 있는 걸까요?
!/bin/bash
ZEN="--info --text \"pure info\" --title \"get info\""
zenity $ZEN
스크립트는 "텍스트의 정보 및 제목의 "jeevan"을 출력합니다. 나머지는 건너뛰는 것입니다.
큰따옴표 안의 공백(특수문자)이 그 특별한 의미를 잃어버리기 때문일까요?
답변1
차이점은 명령이 zenity
첫 번째 경우에는 여러 인수를 볼 수 있지만 두 번째 경우에는 하나의 인수(많은 공백 포함)만 볼 수 있다는 것입니다.
다음 awk
프로그램을 사용하면 쉘이 인수를 확장하는 내용을 빠르게 출력할 수 있습니다. 문제가 발생하면 zsh
문제를 재현할 수 있습니다.
% awk 'BEGIN {for (i in ARGV) print "ARGV["i"] =", ARGV[i]}' $ZEN
ARGV[0] = awk
ARGV[1] = --info --text "pure info" --title "get info"
그리고 bash
그것은 다음과 같아야 합니다(인용된 문자열은 단어로 분할되어 있습니다).
$ awk 'BEGIN {for (i in ARGV) print "ARGV["i"] =", ARGV[i]}' $ZEN
ARGV[0] = awk
ARGV[1] = --info
ARGV[2] = --text
ARGV[3] = "pure
ARGV[4] = info"
ARGV[5] = --title
ARGV[6] = "get
ARGV[7] = info"
이 동작을 처리하는 쉘 토큰화 옵션이 있어야 합니다.
그러나 이것은 작동합니다:
set -- --info --text "pure info" --title "get info"
zenity "$@"
편집하다:
쉘의 단어 분리 기능은 기본적으로 약간 어리석습니다. bash
위 예의 동작을 참조하십시오. "pure
및 info"
두 개의 별도 단어입니다. 명령줄 옵션을 구문 분석할 때 이는 성가신 일이므로 다음은 매뉴얼의 특수 매개변수 섹션 "$@
에서 인용한 내용 입니다.bash
@ Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" ...
일반적인 변수 확장을 특별히 처리하는 방법을 찾지 못했지만 $@
트릭이 있을 수 있습니다.
이 set
명령은 위치 매개변수 $1
, $2
... 를 설정합니다. 따라서 위치 인수의 "모두 제공" 버전 $@
도 사용할 수 있습니다.
답변2
이 문제를 해결하는 한 가지 방법은 eval
문자열 내부의 따옴표가 구문 분석되도록 전체 표현식을 평가하는 것입니다.
eval zenity "$ZEN"
그런데 변수 정의에서 큰따옴표를 이스케이프 처리하는 대신 작은따옴표를 사용할 수도 있습니다.
ZEN='--info --text "pure info" --title "get info"'
#
그건 그렇고, 당신이 이전에 놓쳤던 것 !/bin/bash
.
zsh를 사용하는 경우 또 다른 접근 방식은 플래그와 함께 쉘 구문 분석을 사용하여(인용 부호 고려) 인수를 단어로 분할하는 것 z
입니다. 즉:
zenity "${(z)ZEN}"