답변:
모든 목록 컨텍스트 에서 항상 변수 주위에 따옴표가 필요합니다 . 즉, 변수를 따옴표로 묶지 않은 3 가지 부작용을 원하지 않는 한 변수가 여러 값으로 확장 될 수 있습니다.
리스트 컨텍스트에는 [
or echo
,, for i in <here>
배열에 대한 할당 과 같은 간단한 명령에 대한 인수가 포함 됩니다. 변수를 인용해야하는 다른 컨텍스트도 있습니다. 가장 좋은 이유는 그렇지 않은 이유가없는 한 항상 변수를 인용하는 것입니다.
split + glob 연산자 로 따옴표 (목록 컨텍스트) 가 없다고 생각하십시오 .
마치 것은 echo $test
이었다 echo glob(split("$test"))
.
쉘 동작은 대부분의 사람들에게 혼란 스러울 수 있습니다. 대부분의 다른 언어에서는 puts("foo")
변수와 같은 고정 되지 않은 문자열 주위에 따옴표를 넣고 puts(var)
셸에서는 다른 방법으로 따옴표를 넣습니다. 귀찮을 것입니다 echo test
, 당신은, 당신은 필요하지 않습니다 "echo" "test"
. 셸에서 따옴표는 다른 용도로 사용됩니다. 일부 문자의 특별한 의미를 방지하거나 확장의 동작에 영향을 미칩니다.
에서 [ -n $test ]
또는 echo $test
, 쉘은 분할합니다 $test
(기본적으로 공백에) 한 다음 파일 이름 생성을 수행 (모든 확장 *
, '?'... 패턴과 일치하는 파일의 목록), 다음 인수의 목록을 통과 [
또는 echo
명령 .
다시 한 번 생각하십시오 "[" "-n" glob(split("$test")) "]"
. 경우 $test
비어 있거나 공백 (SPC, 탭, NL)가 포함 된 그래서 다음 분할 + 글로브 연산자는 빈리스트를 반환 [ -n $test ]
될 것 "[" "-n" "]"
"-n"이 빈 문자열인지 처리 여부를 확인하는 시험이다. 그러나 $test
"*"또는 "= foo"인 경우 어떻게되었을 지 상상해보십시오 .
에서 [ -n "$test" ]
, [
네 개의 인수를 전달 "["
, "-n"
, ""
그리고 "]"
우리가 원하는 것을 인 (따옴표없이).
그것의 여부 echo
나 [
차이가 없습니다, 그것은 단지의 echo
같은 것을 출력 해, 하늘의 인수 또는 전혀 인수를 전달 여부.
@ h3rrmiller의 대답 은 왜 if
(또는 오히려 [
/ test
) 따옴표가 필요한지 설명하는 데 유용 하지만 실제로는 귀하의 질문이 잘못되었다고 주장합니다.
다음 명령을 시도하면 무슨 뜻인지 알 수 있습니다.
export testvar="123 456"
echo $testvar
echo "$testvar"
따옴표가 없으면 변수 대체로 인해 두 번째 명령이 다음으로 확장됩니다.
echo 123 456
여러 공간이 단일 공간으로 축소됩니다.
echo 123 456
따옴표를 사용하면 공백이 유지됩니다.
때문에이 문제가 발생 하면 (즉, 매개 변수가 전달되는지 여부를 매개 변수를 인용 할 때 echo
, test
또는 다른 명령), 해당 매개 변수의 값은 다음과 같이 전송 한 명령에 대한 값입니다. 인용하지 않으면 쉘은 공백을 찾는 일반적인 마술을 수행하여 각 매개 변수가 시작하고 끝나는 위치를 결정합니다.
이것은 또한 다음과 같은 (매우 간단한) C 프로그램으로 설명 할 수 있습니다. 명령 행에서 다음을 시도하십시오 (빈 것을 덮어 쓰지 않도록 빈 디렉토리에서 수행 할 수 있습니다).
cat <<EOF >paramtest.c
#include <stdio.h>
int main(int argc, char **argv) {
int nparams = argc-1; /* because 1 parameter means only the executable's name */
printf("%d parameters received\n", nparams);
return nparams;
}
EOF
cc -o paramtest paramtest.c
그리고...
./paramtest 123 456
./paramtest "123 456"
./paramtest 123 456
./paramtest "123 456"
실행 후 paramtest
, $?
매개 변수가 전달되었습니다 (그 번호가 인쇄됩니다)의 수를 개최한다.
이것은 프로그램이 실행 되기 전에 쉘이 어떻게 라인을 해석하는지에 관한 것 입니다.
라인이 읽는 경우 echo I am $USER
, 쉘은 그것을 확장 echo I am blrfl
및 echo
텍스트의 기원은 리터럴 또는 변수 확장을인지 단서가 없습니다. 마찬가지로, 행이 echo I am $UNDEFINED
이면 쉘은 $UNDEFINED
아무것도 확장 되지 않고 echo의 인수는 I am
입니다. 이것이 끝입니다. echo
인수없이 잘 작동 하기 때문에 echo $UNDEFINED
완전히 유효합니다.
와 함께하는 문제 if
는 실제로 어떤 프로그램도 실행 하지 않고 인수가 뒤 따르고 프로그램이 종료되면 (또는 하나가 있고 프로그램이 아닌 경우 ) 부분을 실행 if
하기 때문에 실제로는 아닙니다 .if
then
0
else
0
if /bin/true ; then echo True dat. ; fi
if fgrep -q blrfl /etc/passwd ; then echo Blrfl has an account. ; fi
당신이 사용하는 경우 if [ ... ]
비교 작업을 수행하려면 쉘에 내장 된 기본 요소를 사용하지 않는. 실제로 쉘에 마지막 인수 [
인 test(1)
을 요구 하는 아주 작은 수퍼 세트 라는 프로그램을 실행하도록 지시하고 있습니다 ]
. 0
테스트 조건이 충족되고 그렇지 않은 경우 두 프로그램 모두 종료 됩니다 1
.
변수가 정의되지 않았을 때 일부 테스트가 중단되는 이유는 변수를 사용하고 있지 않기 때문 test
입니다. Ergo, [ $UNDEFINED -eq 2 ]
쉘이 완료 될 때까지 test
인수가 모두 보이 므로 -eq 2 ]
유효한 테스트 가 아니기 때문에 중단됩니다 . 와 같이 정의 된 것으로 수행 한 경우, [ $DEFINED -ne 0 ]
쉘이 유효한 테스트 (예 :)로 확장하기 때문에 작동합니다 0 -ne 0
.
사이에는 의미 상 차이가 있는데 foo $UNDEFINED bar
, 이름에 따라 두 개의 인수 ( foo
와 bar
)로 확장됩니다 $UNDEFINED
. 이것을 세 개의 인수 ( , 빈 문자열 및`bar)로 foo "$UNDEFINED" bar
확장하는와 비교하십시오 . 따옴표는 쉘이 그것들 사이에 어떤 것이 있든 없든, 그것들을 인수로 해석하도록 강제합니다.foo
따옴표 $test
가 없으면 두 단어 이상으로 확장 될 수 있으므로 [
명령 내부의 각 스위치 는 따옴표가하는 하나의 인수를 기대하기 때문에 구문을 위반하지 않기 위해 따옴표가 필요합니다 ( $test
하나의 인수로 확장되는 것은 무엇이든 )
변수를 확장하기 위해 따옴표가 필요하지 않은 이유 echo
는 하나의 인수를 기대하지 않기 때문입니다. 그것은 당신이 말한 것을 단순히 인쇄 할 것입니다. 따라서 $test
100 단어로 확장 하더라도 에코는 여전히 인쇄합니다.
Bash Pitfalls 살펴보기
echo
않습니까?
echo
. 당신이 다르게 생각하게 만드는 것은 무엇입니까?
echo $test
하고 작동합니다 ($ test 값을 출력합니다)
인용되지 않은 경우 빈 매개 변수가 제거됩니다.
start cmd:> strace -e trace=execve echo foo $bar baz
execve("/usr/bin/echo", ["echo", "foo", "baz"], [/* 100 vars */]) = 0
start cmd:> strace -e trace=execve echo foo "$bar" baz
execve("/usr/bin/echo", ["echo", "foo", "", "baz"], [/* 100 vars */]) = 0
호출 된 명령은 쉘 명령 행에 빈 매개 변수가 있음을 알 수 없습니다. [는 -n에 대해 0을 반환하도록 정의되어있는 것 같습니다. 어쨌든
인용은 몇 가지 경우에 반향을 일으키기도합니다.
var='*'
echo $var
echo "$var"
var="foo bar"
echo $var
echo "$var"
echo
셸 이 아닙니다 . 와 동일한 동작을 볼 수 ls
있습니다. 시도 touch '*'
는 모험을 경험하는 경우에 약간의 시간을. :)
echo
추가 공백과 줄 바꿈이 제거됩니다.