私はドットファイルのソース管理に取り組んでいますが、私がやっていることの多くはザック・ホルマンのドットファイル彼がファイルでやっているように、すべての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
出発点です。
まず、 2 行目に示すように、 はディレクトリの下にあるすべてのファイル$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
見た目より簡単ですよね?!;)