数组 – 在Bash完成的上下文中对${array [*]}和${array [@]}的混淆

前端之家收集整理的这篇文章主要介绍了数组 – 在Bash完成的上下文中对${array [*]}和${array [@]}的混淆前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我第一次写一个Bash完成,我有点困惑,关于解除引用Bash数组($ {array [@]}和$ {array [*]})的两种方法

这里是相关的代码块(顺便说一下,它的工作原理,但我想更好地理解它):

  1. _switch()
  2. {
  3. local cur perls
  4. local ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew}
  5. COMPREPLY=()
  6. cur=${COMP_WORDS[COMP_CWORD]}
  7. perls=($ROOT/perls/perl-*)
  8. # remove all but the final part of the name
  9. perls=(${perls[*]##*/})
  10.  
  11. COMPREPLY=( $( compgen -W "${perls[*]} /usr/bin/perl" -- ${cur} ) )
  12. }

Bash的documentation says

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 [@]}扩展到什么。

(这是我对Kaleb Pederson的回答的扩展 – 看看对[@] vs [*]的更一般的对待)

当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选项标志)开始。

更详细:

  1. perls=(perl-one perl-two)
  2. compgen -W "${perls[*]} /usr/bin/perl" -- ${cur}

相当于compgen -W“perl-one perl-two / usr / bin / perl” – $ {cur},它可以做你想要的。另一方面,

  1. perls=(perl-one perl-two)
  2. 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),但显然它只是忽略了他们。

猜你在找的Bash相关文章