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最終的にキャンセルするのではなく無視されます。

おすすめ記事