Что означает этот синтаксис zsh?

Что означает этот синтаксис zsh?

Я работаю над контролем исходного кода моих 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

Это проще, чем кажется, не правда ли?!;)

Связанный контент