ZSH 中的變數範圍:如何從函式內訪問全域變數?
我有一個不斷擴大的
.zshrc
文件,已經失控,所以我決定嘗試通過將其分解為模組化文件並採購每個文件來修復它。這在大多數情況下都有效,但我似乎有一些與變數相關的範圍問題。每個模組文件都包含一個與文件名對應的函式匹配。例如:
nvm..zshrc
包含.zshrc
名為zshrc_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 全域變數可以從另一個函式的範圍內訪問,但不將這些值作為參數傳遞?根據Gilles 的這個回答, “所以,不要再作惡了” ……
export
$$ in $$zsh 是 的簡寫
typeset -gx
,其中屬性g
表示“全域”(相對於函式的局部),屬性x
表示“導出”(即在環境中)。…因此我假設該
$NVM_DIR
變數應該在另一個函式中可用。
您的函式將看到您之前設置的變數(以及是否導出),前提是它們尚未在子 shell 中設置或未聲明為某個已返回的函式的本地變數。
您的問題來自程式碼中不相關的錯誤:
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"
顯然不是空字元串,因此無論$config_file
. 所以你的循環不會做任何事情。您可能的意思是類似
[[ $config_file = .zsh(rc|env) ]]
,儘管這有點毫無意義,因為它們$config_file
永遠不會.zshrc
是.zshenv
隱藏文件,因此預設情況下不包含在 glob 擴展中,並且無論如何$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
參數擴展標誌(例如轉向)/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 var
,您可以local
在函式或匿名函式中使用:function { local var ... }
如果有
$var
來自外部範圍(或來自環境)的 a,那麼它將不理會它,而不是最終取消它。