먼저 zsh를 나머지와 분리하십시오. 오래된 쉘과 현대 쉘의 문제는 아닙니다. zsh는 다르게 동작합니다. zsh 디자이너는 기존 쉘 (Bourne, ksh, bash)과 호환되지 않지만 사용하기 쉽게하기로 결정했습니다.
둘째, 큰 따옴표를 필요할 때 기억하는 것보다 항상 사용하는 것이 훨씬 쉽습니다. 대부분의 시간이 필요하므로 필요할 때가 아니라 필요하지 않은시기를 배워야합니다.
간단히 말해서 단어 목록이나 패턴이 예상되는 곳에는 큰 따옴표가 필요 합니다. 파서가 원시 문자열을 예상하는 상황에서는 선택 사항입니다.
따옴표없이 일어나는 일
큰 따옴표가 없으면 두 가지 일이 발생합니다.
- 먼저, 확장 결과 (와 같은 매개 변수 대체에 대한 변수 값
${foo}
또는 같은 명령 대체에 대한 명령의 출력 $(foo)
)는 공백이 포함 된 곳마다 단어로 분할됩니다.
보다 정확하게는 확장 결과는 IFS
변수 값 (분리 문자)에 나타나는 각 문자로 분할됩니다 . 일련의 구분 문자에 공백 (공백, 탭 또는 줄 바꿈)이 포함 된 경우 공백은 단일 문자로 계산됩니다. 공백이 아닌 구분 기호를 선행, 후행 또는 반복하면 빈 필드가 생깁니다. 예를 들어,와 IFS=" :"
, :one::two : three: :four
이전에 빈 필드를 생산 one
사이 one
와 two
사이에, 그리고 (하나 하나) three
와 four
.
- 분할 결과로 생성 된 각 필드는 문자 중 하나가 포함 된 경우 글로브 (와일드 카드 패턴)로 해석됩니다
\[*?
. 해당 패턴이 하나 이상의 파일 이름과 일치하면 패턴이 일치하는 파일 이름 목록으로 바뀝니다.
인용 부호가없는 변수 확장 $foo
은 구어체 적으로 "split + glob operator"로 알려져 있지만 "$foo"
, 변수의 값만 취합니다 foo
. 명령 대체도 마찬가지 "$(foo)"
입니다. 명령 대체 $(foo)
입니다. 명령 대체는 split + glob입니다.
큰 따옴표를 생략 할 수있는 곳
Bourne 스타일 쉘에서 생각할 수있는 모든 경우는 큰 따옴표없이 변수 또는 명령 대체를 쓸 수 있으며 값은 문자 그대로 해석됩니다.
과제의 오른쪽에.
var=$stuff
a_single_star=*
뒤에 큰 따옴표가 필요합니다 export
. 키워드가 아닌 일반적인 내장 기능이기 때문입니다. 이것은 대시, zsh (sh 에뮬레이션에서), yash 또는 posh와 같은 일부 쉘에서만 적용됩니다. bash와 ksh는 모두 export
특별하게 취급 합니다.
export VAR="$stuff"
A의 case
문.
case $var in …
대소 문자 패턴에는 큰 따옴표가 필요합니다. 대소 문자 패턴에서는 단어 분리가 발생하지 않지만 인용되지 않은 변수는 패턴으로 해석되고 인용 된 변수는 리터럴 문자열로 해석됩니다.
a_star='a*'
case $var in
"$a_star") echo "'$var' is the two characters a, *";;
$a_star) echo "'$var' begins with a";;
esac
이중 괄호 안에 이중 괄호는 쉘 특수 구문입니다.
[[ -e $filename ]]
패턴 또는 정규식이 예상되는 경우에는 큰 따옴표가 필요하다는 점을 제외하고 : =
또는 ==
or !=
또는 오른쪽에 =~
.
a_star='a*'
if [[ $var == "$a_star" ]]; then echo "'$var' is the two characters a, *"
elif [[ $var == $a_star ]]; then echo "'$var' begins with a"
fi
작은 괄호 안에는 큰 따옴표가 필요합니다. 대괄호 [ … ]
는 일반적인 셸 구문이기 때문입니다 (라고하는 명령입니다 [
). 단일 또는 이중 괄호 참조
비 대화식 POSIX 셸에서 리디렉션 (not bash
및 nor ksh88
)
echo "hello world" >$filename
일부 쉘은 대화식 일 때 변수 값을 와일드 카드 패턴으로 처리합니다. POSIX는 비 대화식 쉘에서의 동작을 금지하지만 bash (POSIX 모드 제외) 및 ksh88 ( sh
Solaris와 같은 일부 상용 Unices의 POSIX로 발견 된 경우 포함)을 포함한 일부 쉘은 여전히 그렇게합니다 ( 분할bash
시도도 함) 그 않는 한 리디렉션이 실패 분할이 글 로빙 + 정확히 하나 개의 단어에 결과를 그것에서 리디렉션의 목표를 인용하는 것이 좋습니다 이유입니다,) 당신이로 변환 할 경우에 스크립트 위치를 시스템에 언젠가 스크립트 또는 실행 입니다 해당 지점에서 호환되지 않거나 대화식 쉘에서 제공 될 수 있습니다 .sh
bash
sh
산술 표현식 내부. 실제로 변수를 산술 표현식으로 구문 분석하려면 따옴표를 생략해야합니다.
expr=2*2
echo "$(($expr))"
그러나 POSIX에서 요구하는대로 대부분의 쉘에서 단어 분할이 적용되므로 산술 확장에 따옴표가 필요합니다 (!?).
연관 배열 아래 첨자.
typeset -A a
i='foo bar*qux'
a[foo\ bar\*qux]=hello
echo "${a[$i]}"
인용되지 않은 변수 및 명령 대체는 드문 경우에 유용 할 수 있습니다.
- 변수 값 또는 명령 출력이 glob 패턴 목록으로 구성되고 이러한 패턴을 일치하는 파일 목록으로 확장하려는 경우.
- 값에 와일드 카드 문자가 포함되어 있지 않다는 것을 알면
$IFS
수정되지 않았으며 공백 문자로 분할하려고합니다.
- 특정 문자에서 값을 분할하려면을 사용하여 globbing을 비활성화 하고 구분 문자로
set -f
설정 IFS
하거나 공백으로 분리하려면 그대로 두십시오.
Zsh
zsh에서는 몇 가지 예외를 제외하고 대부분 큰 따옴표를 생략 할 수 있습니다.
$var
여러 단어로 확장되지는 않지만 값이 var
빈 문자열 인 경우 빈 목록 (한 개의 빈 단어가 포함 된 목록과 반대)으로 확장됩니다 . 대조:
var=
print -l $var foo # prints just foo
print -l "$var" foo # prints an empty line, then foo
마찬가지로, "${array[@]}"
배열의 모든 요소로 $array
확장되고 비어 있지 않은 요소로만 확장됩니다.
@
매개 변수 확장 플래그 때로는 전체 대체 주위에 따옴표가 필요합니다 "${(@)foo}"
.
: 명령 치환은 필드 분할 인용 부호로 둘러싸이지 않은 경우에 거쳐 echo $(echo 'a'; echo '*')
인쇄 a *
반면 (하나의 공간) echo "$(echo 'a'; echo '*')"
수정되지 않은 두 줄의 문자열을 인쇄합니다. 한 "$(somecommand)"
줄로 명령의 출력을 얻기 위해 사용하십시오 . "${$(somecommand; echo _)%?}"
최종 개행을 포함하여 명령의 정확한 출력을 얻는 데 사용하십시오 . "${(@f)$(somecommand)}"
명령 출력에서 행 배열을 가져 오는 데 사용 합니다.
SH_WORD_SPLIT
옵션의 영향을받습니다 .