我第一次尝试编写Bash补全,这让我有些困惑,因为这两种取消引用Bash数组(${array[@]}和${array[*]})的方式。
这是相关的代码块(顺便说一句,它可以工作,但是我想更好地理解它):
_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的文档说:
数组的任何元素都可以使用$ {name [subscript]}进行引用。需要使用花括号来避免与Shell的文件名扩展运算符冲突。如果下标为'@'或'*',则单词将扩展为数组名称的所有成员。仅当单词出现在双引号中时,这些下标才不同。如果单词用双引号引起来,则$ {name [*]}扩展为一个单词,每个数组成员的值均由IFS变量的第一个字符分隔,而$ {name [@]}扩展每个name元素换一个词。
现在,我想我理解了compgen -W期望包含一个可能的替代词列表的字符串,但是在这种情况下,我不理解“ $ {name [@]}将名称的每个元素扩展为一个单独的词”的含义。
长话短说:${array[*]}作品;${array[@]}没有。我想知道为什么,并且我想更好地理解将要${array[@]}扩展的内容。 问题来源于stack overflow
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
(这是我对Kaleb Pederson的回答的评论的扩展-有关[@]vs 的更一般性处理,请参见该回答[*]。)
当bash(或任何类似的shell)解析命令行时,它将其分成一系列“单词”(为避免混淆,我将其称为“ shell-words”)。通常,shell词由空格(或其他空白)分隔,但是可以通过转义或引用空格来将空格包含在shell词中。[@]和- [*]扩展数组中双引号之间的区别是,"${myarray[@]}"导致将数组的每个元素都视为一个单独的shell字,而"${myarray[*]}"导致单个shell字,其中数组的所有元素都由空格(或不管第一个字符IFS是什么)。
通常,[@]行为就是您想要的。假设我们拥有perls=(perl-one perl-two)并使用ls "${perls[*]}"-等效于ls "perl-one perl-two",它将查找名为的单个文件perl-one perl-two,这可能不是您想要的。 ls "${perls[@]}"等价于ls "perl-one" "perl-two",这很有可能会做一些有用的事情。
提供的补全单词列表(为了避免与shell单词混淆,我将其称为comp-words)compgen;该-W选项采用comp-word列表,但必须采用单个shell字的形式,且comp-word之间用空格分隔。请注意,带有参数的命令选项始终(至少就我所知)使用单个shell字-否则,将无法分辨该选项的参数何时结束以及常规命令参数(/ 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标志的唯一comp-word,第一个实参(compgen将作为要完成的字符串)是“ perl-2” / usr / bin / perl”。我希望compgen抱怨它被赋予了额外的参数(“-”以及$ cur中的任何内容),但显然它只是忽略了它们。