这里是相关的代码块(顺便说一下,它的工作原理,但我想更好地理解它):
_switch() { local cur perls local ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew} COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} perls=($ROOT/perls/perl-*) # remove all but the final part of the name perls=(${perls[*]##*/}) COMPREPLY=( $( compgen -W "${perls[*]} /usr/bin/perl" -- ${cur} ) ) }
Bash的documentation says:
@H_404_7@Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with the shell’s filename expansion operators. If the subscript is ‘@’ or ‘*’,the word expands to all members of the array name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted,${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable,and ${name[@]} expands each element of name to a separate word.
现在我想我理解compgen -W期望一个字符串包含可能的替代品的wordlist,但在这个上下文中,我不明白什么“$ {name [@]}扩展名称的每个元素到一个单独的单词”的意思。
长故事:$ {array [*]}工作; $ {array [@]}不。我想知道为什么,我想更好地理解$ {array [@]}扩展到什么。
当Bash(或任何类似的shell)解析命令行时,它将它分成一系列“单词”(我将称为“shell单词”,以避免以后混淆)。通常,字词由空格(或其他空格)分隔,但是空格可以通过转义或引用而包括在单词中。双引号中[@]和[*] – 展开数组之间的区别是,“$ {myarray [@]}”导致数组的每个元素被视为单独的shell-word,而“$ {myarray [ *]}“结果是一个单独的shell-word,数组的所有元素都用空格(或IFS的第一个字符)分隔。
通常,[@]行为是你想要的。假设我们有perls =(perl-one perl-two)并使用ls“$ {perls [*]}” – 这相当于ls“perl-one perl-two”,它将寻找单个文件名为perl-one perl-two,这可能不是你想要的。 ls“$ {perls [@]}”等价于ls“perl-one”“perl-two”,这更有可能做一些有用的事情。
提供一个完成词列表(我将称之为comp-words以避免与shell-words混淆)到compgen是不同的; -W选项接受一个复合词列表,但它必须是一个单独的壳单词的形式,复合词用空格分隔。注意,接受参数的命令选项总是(至少就我所知)采用一个shell-word – 否则没有办法告诉选项的参数何时结束,以及常规的命令参数(/ other选项标志)开始。
更详细:
perls=(perl-one perl-two) compgen -W "${perls[*]} /usr/bin/perl" -- ${cur}
相当于compgen -W“perl-one perl-two / usr / bin / perl” – $ {cur},它可以做你想要的。另一方面,
perls=(perl-one perl-two) compgen -W "${perls[@]} /usr/bin/perl" -- ${cur}
相当于compgen -W“perl-one”“perl-two / usr / bin / perl” – $ {cur},这是完全无意义的:“perl-one”是唯一的附加到-W标志,而第一个真实参数 – 即compgen将作为要完成的字符串 – 是“perl-two / usr / bin / perl”。我期望compgen抱怨它已经被给予额外的参数(“ – ”和任何在$ cur),但显然它只是忽略了他们。