Я работаю над контролем исходного кода моих dotfiles и многое из того, что я делаю, основано наdotfiles Зака Холмана. Я хочу получить исходники всех файлов zsh, как он делает в своих файлах, но прежде чем просто вставить туда код, я хочу на самом деле понять, что делает код. Фрагмент, который меня смущает, это
# all of our zsh files
typeset -U config_files
config_files=($ZSH/**/*.zsh)
# load the path files
for file in ${(M)config_files:#*/path.zsh}
do
source $file
done
# load everything but the path and completion files
for file in ${${config_files:#*/path.zsh}:#*/completion.zsh}
do
source $file
done
# initialize autocomplete here, otherwise functions won't be loaded
autoload -U compinit
compinit
# load every completion after autocomplete loads
for file in ${(M)config_files:#*/completion.zsh}
do
source $file
done
unset config_files
В основном я не понимаю, что здесь происходит.
${(M)config_files:#*/path.zsh}
и здесь
${${config_files:#*/path.zsh}:#*/completion.zsh}
Итак, что же все это значит?
решение1
Раздел страницы PARAMETER EXPANSION
руководства zshexpn
является хорошей отправной точкой.
Во-первых, отметим, что $config_files
это массив, включающий все .zsh
файлы в $ZSH
каталоге, как вы можете видеть во второй строке: config_files=($ZSH/**/*.zsh)
.
Этот синтаксис, используемый в строке ${(M)config_files:#*/path.zsh}
(обратите внимание, что M
внутри скобок называетсяфлаг расширения) выглядит следующим образом:
${name:#pattern}
If the pattern matches the value of name, then substitute the
empty string; otherwise, just substitute the value of name.
If name is an array the matching array elements are removed
(use the `(M)' flag to remove the non-matched elements).
Другими словами, рассматриваемый цикл for перебирает все path.zsh
файлы в $ZSH. Вы могли бы использовать for file in $ZSH/**/path.zsh
его, но операция с $config_files
массивом файлов быстрее, чем рекурсивный поиск в файловой системе снова и снова. (Есть еще циклы for, не так ли?)
Обладая этими знаниями, будет легко понять, что ${${config_files:#*/path.zsh}:#*/completion.zsh}
делать. (Результат в любом случае указан в комментарии).
Я обычно привожу несколько тривиальных примеров, чтобы лучше понять:
$ array=(foo bar baz)
$ print ${array}
foo bar baz
$ print ${array:#ba*}
foo
$ print ${(M)array:#ba*}
bar baz
Это проще, чем кажется, не правда ли?!;)