ZSH 로그인 시 precmd_functions에 기능을 추가하고 중복을 방지하고 싶습니다. /etc/zprofile은 /etc/profile을 소스로 하고 /etc/profile.d/ 아래의 모든 *.sh 스크립트를 소스로 만들기 때문에 내 해결책은 init 스크립트를 /etc/profile.d에 추가하는 것이었습니다. Bash와의 호환성을 유지하기 위해 자동 소스 스크립트 new_script.sh
는 다음과 같습니다.
# zsh user
if [ -n "$ZSH_VERSION" ]; then
source /etc/profile.d/new_script.zsh
# bash user
elif [ -n "$BASH_VERSION" ]; then
source /etc/profile.d/new_script.bash
fi
이 시점까지는 모든 것이 녹색이지만 new_script.zsh는 이상하게 동작합니다. 그 내용은 다음과 같습니다.
...
if (( $precmd_functions[(I)audit_hook] )); then
hook_exist=true
else
hook_exist=false
fi
zsh를 사용하여 로그인한 후 수동으로 가져오면 문제 없이 실행됩니다. 그러나 로그인 초기화 중에 자동으로 가져오면 bad output format specification
행에 보고 됩니다 if (( $precmd_functions...
.
그렇다면 init에 로그인할 때만 이 오류가 보고되고 수동 가져오기 스크립트에서는 보고되지 않는 이유는 무엇입니까?
답변1
아래의 파일은 /etc/profile.d
sh 구문으로 작성될 것으로 예상되므로 /etc/zprofile
소스의 코드는 /etc/profile.d/*
아마도 다음과 같은 sh 또는 ash 에뮬레이션 모드에서 이 작업을 수행하도록 배열되어 있을 것입니다 emulate ksh -c '. /etc/profile'
.
sh와 zsh 구문의 차이점 중 하나는 $foo[bar]
zsh에서는 배열 변수 역참조로 구문 분석되지만 sh(및 bash 및 zsh와 같은 호환 쉘)에서는 단일 문자 glob이 뒤에 오는 문자열 변수라는 것입니다(따라서 sh로 touch somefilename1 somefilename2 somefilename3; var=somefilename; echo $var[12]
인쇄됨 somefilename1 somefilename2
/bash/ksh, 그러나 e
zsh에는 없음). zsh가 sh 또는 ksh 에뮬레이션 모드에 있을 때,zsh_arrays
$precmd_functions[(I)audit_hook]
옵션이 활성화되어 있으므로 어레이 액세스로 확인되지 않습니다 . precmd_functions
이 시점에서는 비어 있으므로(그렇지 않은 경우 다른 오류가 발생할 가능성이 높음) 산술 표현식은 가 됩니다 [(I)audit_hook]
. zsh의 브래킷 부분산술 표현출력 형식 사양은 출력이 다른 기준으로 형식화되도록 지시하는 출력 형식 사양입니다(몇 가지 다른 가능성 중에서 이것이 단지 출력 기반 사양이 아닌 이유입니다). zsh가 여는 괄호를 보면 출력 형식 사양을 구문 분석할 준비를 하지만 실패합니다.
zsh 관련 코드를 작성 /etc/profile.d
하고 zsh 구문을 사용하려는 경우 zsh 구문을 사용하도록 zsh에 명시적으로 지시합니다.
if [ -n "$ZSH_VERSION" ]; then
emulate zsh -c 'source /etc/profile.d/new_script.zsh'
fi
아니면 모든 코드를 new_script.zsh
함수에 넣고emulate -L zsh
함수 상단에 있습니다. (함수 외부에 두지 마십시오 emulate -L …
. 소스 스크립트에 로컬이 아닙니다.)