단일 또는 이중 괄호를 사용하는 것이 혼란스럽습니다. 이 코드를 보세요:
dir="/home/mazimi/VirtualBox VMs"
if [[ -d ${dir} ]]; then
echo "yep"
fi
문자열에 공백이 포함되어 있어도 정상적으로 작동합니다. 하지만 단일 대괄호로 변경하면 다음과 같습니다.
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then
echo "yep"
fi
그것은 말한다:
./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected
내가 그것을 다음과 같이 바꿀 때 :
dir="/home/mazimi/VirtualBox VMs"
if [ -d "${dir}" ]; then
echo "yep"
fi
좋은 결과. 무슨 일인지 설명해 줄 수 있는 사람이 있나요? 예를 들어 "${var}"
공백으로 인한 문제를 방지하려면 언제 변수 주위에 큰따옴표를 지정해야 합니까 ?
답변1
단일 대괄호는 [
실제로 명령의 별칭입니다 test
.아니요통사론.
단일 괄호의 단점 중 하나는 평가하려는 피연산자 중 하나 이상이 빈 문자열을 반환하는 경우 두 개의 피연산자(이진수)가 필요하다고 불평한다는 것입니다. 이것이 바로 사람들 이 피연산자가 빈 문자열로 평가되지 않도록 보장하면서 [ x$foo = x$blah ]
이렇게 하는 것을 보는 이유입니다 .x
[[ ]]
반면에 이중 괄호는문법이야그리고 [ ]
. 발견한 대로 "피연산자 누락" 문제가 발생하지 않으며 C와 유사한 연산자 구문도 더 많이 허용합니다 >, <, >=, <=, !=, ==, &&, ||
.
내 조언은 이렇습니다: 만약 당신의 통역사 #!/bin/bash
가언제나사용[[ ]]
[[ ]]
모든 POSIX 쉘이 이를 지원하는 것은 아니지만 많은 쉘이 이를 지원한다는 zsh
점 은 주목할 가치가 있습니다 .ksh
bash
답변2
이 [
명령은 일반적인 명령입니다. 대부분의 쉘은 효율성을 위해 내장 함수로 제공하지만 쉘의 일반 구문 규칙을 따릅니다. 필수가 아닌 마지막 인수로 a가 필요 하다는 점을 제외하면 [
와 정확히 동일합니다 .test
[
]
test
이중 괄호는 [[ … ]]
특수 구문입니다. 사용이 번거롭고 쉘 특수 문자에 몇 가지 새로운 추가 기능을 허용하기 때문에 ksh(몇 년 후 [
) 에 도입되었습니다. 예를 들어 다음과 같이 쓸 수 있습니다.[
[[
[[ $x = foo && $y = bar ]]
전체 조건식은 쉘에 의해 구문 분석되므로 while 은 먼저 연산자로 구분된 [ $x = foo && $y = bar ]
두 개의 명령으로 분할됩니다 . 마찬가지로 이중 괄호를 사용 하면 값이 ;로 시작하는지 테스트하는 등의 패턴 일치 구문과 같은 작업이 가능합니다 . 단일 괄호 안에 있으면 현재 디렉터리의 이름으로 시작하는 파일 목록이 확장됩니다 . 이중 괄호는 ksh에서 처음 도입되었으며 ksh, bash 및 zsh에서만 사용할 수 있습니다.[ $x = foo
$y = bar ]
&&
[[ $x == a* ]]
x
a
a*
a
작은 괄호 안에는 대부분의 다른 위치에서와 마찬가지로 변수 대체 주위에 큰따옴표를 사용해야 합니다. 이는 명령에 대한 인수일 뿐이기 때문입니다( command [
). 큰 괄호 안에는 큰따옴표가 필요하지 않습니다. 쉘은 단어 분리나 와일드카드를 수행하지 않기 때문입니다. 이는 명령이 아닌 조건식을 구문 분석하는 것입니다.
한 가지 예외는 [[ $var1 = "$var2" ]]
바이트 간 문자열 비교를 수행하려는 경우 따옴표가 필요하다는 것입니다. 그렇지 않으면 $var2
일치하는 패턴이 됩니다 $var1
.
당신이 할 수 없는 한 가지는 [[ … ]]
변수를 연산자로 사용하는 것입니다. 예를 들어, 다음은 완전히 합법적이지만 거의 유용하지 않습니다.
if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi
…
if [ "$x" "$op" "$y" ]; then …
귀하의 예에서
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then …
내부 명령에는 , , 4 개의 매개변수가 if
있습니다 . 쉘은 그것을 구문 분석한 후에 무엇을 해야 할지 모릅니다 . 올바른 형식의 명령을 얻으려면 단어 분리를 방지해야 합니다 .[
-d
/home/mazimi/VirtualBox
VMs
]
-d /home/mazimi/VirtualBox
VMs
${dir}
일반적으로 결과에 대해 토큰화 및 와일드카드를 수행하려는 경우가 아니면 항상 변수 및 명령 대체 주위에 큰따옴표를 사용하십시오. 큰따옴표를 사용하지 않는 것이 안전한 주요 위치는 다음과 같습니다.
- 할당에서: (그러나
foo=$bar
예를 들어 배열 할당 내에서는 큰따옴표가 필요합니다.)export "foo=$bar"
array=("$a" "$b")
case
성명서 에서 :case $foo in …
;=
or 연산자의 오른쪽을 제외한 이중 괄호 내==
(실제로 패턴 일치가 필요한 경우 제외):[[ $x = "$y" ]]
.
모두 큰 따옴표를 사용하는 것이 정확하므로 고급 규칙을 건너뛰고 항상 따옴표를 사용하는 것이 좋습니다.
답변3
"${var}"
예를 들어 공백으로 인한 문제를 방지하려면 언제 변수 주위에 큰따옴표를 지정해야 합니까 ?
이 질문에 암시적인 것은
왜 충분하지 않습니까?
${variable_name}
${variable_name}
당신이 생각하는 그런 의미는 아니죠...
...그렇다고 생각한다면아무것변수 값에서 공백이나 "glob"(파일 이름 패턴) 문자로 인해 발생한 문제를 처리합니다. 이것에 좋습니다:${variable_name}
$ bar=foo
$ bard=Shakespeare
$ echo $bard
Shakespeare
$ echo ${bar}d
food
다른 건 없어! 1 하지마${variable_name}
어느A
변수 이름의 일부일 수 있는 문자(문자( - Z
또는 a
- z
), 밑줄( _
) 또는 숫자( 0
- )) 가 뒤에 오지 않는 한 괜찮습니다 9
. 그럼에도 불구하고 문제를 해결할 수 있습니다.
$ echo "$bar"d
food
또는
$ fourth_letter=d
$ echo $bar$fourth_letter
food
나는 그것의 사용을 막으려는 것이 아니라(
echo "${bar}d"
아마도 최선의 해결책일 것입니다) 사람들이 교정기에 의존하는 것을 막으려는 것입니다.바꾸다따옴표를 사용하거나 본능적으로 중괄호를 사용하여 “이제 따옴표가 필요한가요?반품?"
타당한 이유가 없고 자신이 하고 있는 일을 확실히 알고 있지 않는 한 항상 따옴표를 사용해야 합니다.
________________ 1 물론 다음과 같은 경우는
제외됩니다 .매개변수 확장, , 및 , 와 같은 문법은 문법을 기반으로 합니다. 또한 등을 사용하여 10번째, 11번째 등의 위치 매개변수를 인용해야 합니다. - 인용은 이에 도움이 되지 않습니다.${parameter:-[word]}
${parameter%[word]}
${#parameter}
${parameter^^}
${parameter}
${10}
${11}
답변4
변수에서 공백과 공백 | 특수 문자를 처리하려면 항상 큰따옴표로 묶어야 합니다. 적절한 IFS를 설정하는 것도 좋은 방법입니다.
존경받는다: http://www.dwheeler.com/essays/filenames-in-shell.html