변수의 전역 문자는 bash에서는 확장되지만 zsh에서는 확장되지 않습니다.

변수의 전역 문자는 bash에서는 확장되지만 zsh에서는 확장되지 않습니다.

변수의 전역 문자가 예상대로 확장되지 않는 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에 의해 지정됨). 이로 인해 많은 버그와 보안 허점이 발생합니다. 이것이 바로 이 쉘의 모든 변수를 인용해야 하는 이유입니다.bashsh

예를 들면 다음을 참조하세요.bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험

나는 당신이 글을 쓸 때에도 이것을 기대하고 있다는 것을 알았 echo $0습니다 echo "$0".

zsh이 문제는 해결되었습니다. 기본적으로 매개변수 확장 중에 와일드카드나 토큰화를 수행하지 않습니다. 다음을 명시적으로 요청해야 합니다.

  • echo $=file: 단어 분할 실행
  • echo $~file: 와일드카드 실행
  • echo $=~file: 둘 다 실행

globsubst또는 Bourne과 같은 쉘에서와 동일한 동작을 얻기 위해 및 옵션을 설정할 수 있지만 ( shwordsplit호환성을 요구할 때 두 옵션 모두 활성화됨), 다른 쉘용으로 작성된 코드를 해석해야 하는 경우가 아니면 이 방법을 권장하지 않습니다(심지어 이 경우 )를 사용하여 로컬 컨텍스트에서 해당 코드 해석을 시뮬레이션하는 것이 더 합리적입니다.zshshshzshshemulate -L sh

file여기에 변수 이름을 지정하세요.

file=*

다음과 같은 경우에 연장하려는 경우 이는 오해의 소지가 있습니다.

filename_pattern=*

더 이해가 될 것입니다. 현재 디렉터리에 숨겨져 있지 않은 모든 파일의 이름을 변수에 저장하려면 다음과 같이 할 수 있습니다.

files=(*)

또는:

files=(*(N))

현재 디렉터리에 숨겨지지 않은 파일이 없으면 할당이 실패하지 않습니다.

즉,대량으로변수 할당. ( ) 는 일치 항목이 없을 때 패턴이 확장되지 않는다는 Bourne 쉘의 다른 버그 기능이 없다는 점을 제외하면 or 또는 or 와 file=(*)동일한 방식으로 작동합니다 .bashksh93mkshyashzsh


*¹이 이름은 Unix 계열 시스템의 파일에 대해 완벽하게 유효한 이름입니다. 파일을 불러도 rm -f -- $file이름이 저장되어 있는 파일은 삭제된다는 점에서 조금은 위안을 받습니다.$file*

관련 정보