변수의 전역 문자가 예상대로 확장되지 않는 zsh 문제를 발견했습니다. 다음 예는 이를 더 잘 설명합니다.
$ echo $0
-bash
$ echo $HOME/Downloads/zsh-test/*
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4
$ file=*; echo $HOME/Downloads/zsh-test/$file
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4
Macbook% echo $0
zsh
Macbook% echo $HOME/Downloads/zsh-test/*
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4
Macbook% file=*; echo $HOME/Downloads/zsh-test/$file
/Users/bruce/Downloads/zsh-test/*
나는 마지막 명령이 bash처럼 확장될 것으로 기대했습니다. 내가 뭘 잘못하고 있는지 아시나요?
답변1
누군가가 이것에 대해 불평하는 것을 본 것은 이번이 처음이 될 것입니다(우리는 사람들이 인수 확장 시 토큰화를 수행하지 않는다고 불평하는 것을 더 자주 봅니다).
대부분의 사람들은 기대한다
echo $file
변수의 내용을 인쇄하고 이와 같은 쉘이 인쇄되지 않을 때 짜증이 납니다 $file
(Bourne 쉘에서 상속된 동작, 불행하게도 ksh에 의해 수정되지 않고 인터프리터를 위해 POSIX에 의해 지정됨). 이로 인해 많은 버그와 보안 허점이 발생합니다. 이것이 바로 이 쉘의 모든 변수를 인용해야 하는 이유입니다.bash
sh
예를 들면 다음을 참조하세요.bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험
나는 당신이 글을 쓸 때에도 이것을 기대하고 있다는 것을 알았 echo $0
습니다 echo "$0"
.
zsh
이 문제는 해결되었습니다. 기본적으로 매개변수 확장 중에 와일드카드나 토큰화를 수행하지 않습니다. 다음을 명시적으로 요청해야 합니다.
echo $=file
: 단어 분할 실행echo $~file
: 와일드카드 실행echo $=~file
: 둘 다 실행
globsubst
또는 Bourne과 같은 쉘에서와 동일한 동작을 얻기 위해 및 옵션을 설정할 수 있지만 ( shwordsplit
호환성을 요구할 때 두 옵션 모두 활성화됨), 다른 쉘용으로 작성된 코드를 해석해야 하는 경우가 아니면 이 방법을 권장하지 않습니다(심지어 이 경우 )를 사용하여 로컬 컨텍스트에서 해당 코드 해석을 시뮬레이션하는 것이 더 합리적입니다.zsh
sh
sh
zsh
sh
emulate -L sh
file
여기에 변수 이름을 지정하세요.
file=*
다음과 같은 경우에 연장하려는 경우 이는 오해의 소지가 있습니다.
filename_pattern=*
더 이해가 될 것입니다. 현재 디렉터리에 숨겨져 있지 않은 모든 파일의 이름을 변수에 저장하려면 다음과 같이 할 수 있습니다.
files=(*)
또는:
files=(*(N))
현재 디렉터리에 숨겨지지 않은 파일이 없으면 할당이 실패하지 않습니다.
즉,대량으로변수 할당. ( ) 는 일치 항목이 없을 때 패턴이 확장되지 않는다는 Bourne 쉘의 다른 버그 기능이 없다는 점을 제외하면 or 또는 or 와 file=(*)
동일한 방식으로 작동합니다 .bash
ksh93
mksh
yash
zsh
*
¹이 이름은 Unix 계열 시스템의 파일에 대해 완벽하게 유효한 이름입니다. 파일을 불러도 rm -f -- $file
이름이 저장되어 있는 파일은 삭제된다는 점에서 조금은 위안을 받습니다.$file
*