ZSH의 변수 범위: 함수 내에서 전역 변수에 액세스하는 방법은 무엇입니까?

ZSH의 변수 범위: 함수 내에서 전역 변수에 액세스하는 방법은 무엇입니까?

계속해서 확장되는 .zshrc파일이 있어서 감당할 수 없게 되었기 때문에 파일을 모듈식 파일로 나누고 각각 가져가서 수정해 보기로 결정했습니다. 이것은 대부분 작동하지만 변수에 범위 지정 문제가 있는 것 같습니다.

각 모듈 파일에는 파일 이름에 해당하는 함수가 포함되어 있습니다. 예: ( 메인 파일에서 호출됨) nvm..zshrc이라는 함수가 포함되어 있습니다 ..zshrczshrc_config_load_nvm {}

다음은 제가 사용하고 있는 설정의 단순화된 형태입니다.

기본 .zshrc 파일

이 파일을 철저하게 테스트했으며 그 안에 있는 모든 것이 잘 작동한다는 점에 유의하세요.

# Load all config files 
# This method basically copied directly from the .oh-my-zsh.sh file.
for config_file ($ZSH_CUSTOM/*.zshrc(N)); do

    # Skip self-inclusion
    if [[ $config_file==".zshrc" || $config_file==".zshenv" ]]; then
        continue
    fi
    
    # The (D) modifier will escape the path so it can be passed to `basename`
    # without quotes. the second param in `basename` removes the file extension.
    local handle=$(basename ${(D)config_file} .zshrc)

    # If the file contains the expected callback function name ...
    # The :t filter will remove the path and file extension.
    if [[ $(command -v "zshrc_config_load_${handle}") ]]; then
        
        # ... Add it to the list of functions to call.
        ZSH_CONFIG_HANDLES+=($handle)
    fi
    # Each config file will call the register function above.
    source $config_file
done

for handle ($ZSH_CONFIG_HANDLES); do

    func="zshrc_config_load_${handle}"

    # Call the function
    $func
done
unset config_file handle func

nvm.zshrc

# This line is copied directly from the documentation. 
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"



# The callback function
function zshrc_config_load_nvm {
    
    # Unable to access the $NVM_DIR variable in this scope. 
    source $NVM_DIR/nvm.sh --fast-reuse
    # Error: /nvm.sh does not exist.
}

질문

export다른 함수의 범위에서 ed 전역 변수에 액세스할 수 있지만 값을 매개변수로 전달하지 못하게 하려면 어떻게 해야 합니까 ?

~에 따르면이 답변통과자일스 "그럼 악한 짓은 그만둬"...

export[in] zsh는 zsh의 약어입니다 typeset -gx. 여기서 속성은 g"전역"(함수에 대한 로컬과 반대)을 의미하고 속성은 x"내보낸"(즉, 환경에서)을 의미합니다.

$NVM_DIR...그래서 변수를 다른 함수에서 사용할 수 있어야 한다고 가정합니다 .

답변1

함수는 서브셸에서 설정되지 않았거나 반환된 함수 중 하나에서 로컬 변수로 선언되지 않은 경우 이전에 설정한 변수(내보내기 여부에 관계없이)를 볼 수 있습니다.

문제는 코드의 관련 없는 오류로 인해 발생합니다.

for config_file ($ZSH_CUSTOM/*.zshrc(N)); do

    # Skip self-inclusion
    if [[ $config_file==".zshrc" || $config_file==".zshenv" ]]; then
        continue
    fi

[[ somestring ]]somestring빈 문자열이 아닌 경우 true를 반환합니다. $config_file==".zshrc"분명히 빈 문자열이 아니므로 test는 값에 관계없이 true를 반환합니다 $config_file. 따라서 루프는 아무 작업도 수행하지 않습니다.

아마 그런 뜻일 것입니다 . 비록 숨김 파일이 아니므 로 기본적으로 전역 확장에 포함되지 않고 어쨌든 로 시작 하고 끝나지 않기 때문에 [[ $config_file = .zsh(rc|env) ]]약간 무의미하기는 하지만 .$config_file.zshrc.zshenv$config_file/path/to/zsh_custome/.zshenv.zshrc

if [[ $config_file -ef $0 ]] continue$config_file이것이 현재 가져오는 스크립트가 아닌지 확인하는 것이 더 합리적일 수 있습니다.

기타 참고사항:

 export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"

다음과 같이 작성하는 것이 좋습니다.

if (( $+XDG_CONFIG_HOME )); then
  export NVM_DIR=$XDG_CONFIG_HOME/nvm
else
  export NVM_DIR=~/.nvm
fi

존재하다:

  local handle=$(basename ${(D)config_file} .zshrc)

매개변수 D확장 플래그(예: make /home/you/file) 에는 ~/file의미가 없습니다.

당신이 원하는 것 같네요 local handle=$config_file:t:r(뿌리~의꼬리파일).

  if [[ $(command -v "zshrc_config_load_${handle}") ]];

다음과 같이 쓰는 것이 더 좋습니다:

if command -v "zshrc_config_load_${handle}" >& /dev/null;

이렇게 하면 끝이 갈라지는 것을 방지할 수 있습니다. 아니면 if (( $+functions[zshrc_config_load_${handle}] ));

... 을 수행하는 대신 함수 또는 익명 함수 내부에서 사용할 수 있습니다 var=....unset varlocal

function {
  local var
  ...
}

외부 범위(또는 환경)에 있는 경우 $var결국 취소하는 대신 무시됩니다.

관련 정보