一个混淆$ {数组[*]}与$ {数组[@]}在完成击的情况下 [英] A confusion about ${array[*]} versus ${array[@]} in the context of a Bash completion
问题描述
我正在刺伤编写完成猛砸,第一次,我有点困惑约提领猛砸阵列的两种方式( $ {数组[@]}
和 $ {数组[*]}
)。
I'm taking a stab at writing a Bash completion for the first time, and I'm a bit confused about about the two ways of dereferencing Bash arrays (${array[@]}
and ${array[*]}
).
下面是code的(它的工作原理,对了,但我想更好地理解它)有关块:
Here's the relevant chunk of code (it works, by the way, but I would like to understand it better):
_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} ) )
}
击的文件说:
数组的任何元素都可以用$引用{名[下标]}。大括号是必需的,以避免与shell的文件名扩展运营商的冲突。如果下标'@'或'*',字扩展到数组名的所有成员。只有当词出现在双引号内这些标不同。如果字是双引号,$ {名称[*]}扩展到由IFS变量的第一个字符分隔每个数组成员的值一个字,和$ {名称[@]}扩展名的每个元素为一个词。
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
预计包含可能的选择一个单词表一个字符串,但在这种情况下,我不明白什么是$ {名[ @]}扩展为一个词名称中的每个元素的意思。
Now I think I understand that compgen -W
expects a string containing a wordlist of possible alternatives, but in this context I don't understand what "${name[@]} expands each element of name to a separate word" means.
长话短说: $ {数组[*]}
工程; $ {数组[@]}
没有。我想知道为什么,我想更好地了解究竟是什么 $ {数组[@]}
扩展到
Long story short: ${array[*]}
works; ${array[@]}
doesn't. I would like to know why, and I would like to understand better what exactly ${array[@]}
expands into.
推荐答案
(这是我在卡莱布佩德森的回答评论的扩展 - 看到,更一般治疗[@]
VS [*]
)
(This is an expansion of my comment on Kaleb Pederson's answer -- see that for a more general treatment of [@]
vs [*]
.)
当巴什(或任何类似的壳)解析一个命令行,它拆分成一系列的单词(我称之为壳字,后来以避免混淆)。通常,字是由空格(或其它空格)通过转义或引用它们分离,但可以包括空格中的单词。 [@]
和 [*]
在双引号-expanded阵列是$ {myArray的[@]}
导致被视为一个单独的壳字阵列中的每个元素,而$ {myArray的[*]}
结果在一个shell字全部用空格(或任何的第一个字符 IFS
是)分隔数组的元素。
When Bash (or any similar shell) parses a command line, it splits it into a series of "words" (which I will call "shell-words" to avoid confusion later). Generally, words are separated by spaces (or other whitespace), but spaces can be included in a word by escaping or quoting them. The difference between [@]
and [*]
-expanded arrays in double-quotes is that "${myarray[@]}"
leads to each element of the array being treated as a separate shell-word, while "${myarray[*]}"
results in a single shell-word with all of the elements of the array separated by spaces (or whatever the first character of IFS
is).
一般情况下, [@]
的行为是你想要的。假设我们有皮尔斯=(perl的一perl的-二)
,并使用 LS$ {皮尔斯[*]}
- 这是等同于 LS的perl一Perl的两个
,它就会查找名为单个文件 perl的一Perl的两个
,这可能不是你想要的。 LS$ {皮尔斯[@]}
等同于 LS的perl-一Perl的两个
,这是更可能做一些有用的东西。
Usually, the [@]
behavior is what you want. Suppose we have perls=(perl-one perl-two)
and use ls "${perls[*]}"
-- that's equivalent to ls "perl-one perl-two"
, which will look for single file named perl-one perl-two
, which is probably not what you wanted. ls "${perls[@]}"
is equivalent to ls "perl-one" "perl-two"
, which is much more likely to do something useful.
提供了完成单词的列表(我会打电话给补偿字,以避免与外壳字混乱),以 compgen
是不同的;在 -W
选项采用的COMP-单词的列表,但它必须是在一个shell字由空格隔开的样稿词的形式。需要注意的是带参数始终是命令选项(至少据我所知)采取单壳字 - 否则会是没有办法告诉当参数选项结束,在常规命令参数(/其他选项标志)开始。
Providing a list of completion words (which I will call comp-words to avoid confusion with shell-words) to compgen
is different; the -W
option takes a list of comp-words, but it must be in the form of a single shell-word with the comp-words separated by spaces. Note that command options that take arguments always (at least as far as I know) take a single shell-word -- otherwise there'd be no way to tell when the arguments to the option end, and the regular command arguments (/other option flags) begin.
在更多详细信息:
perls=(perl-one perl-two)
compgen -W "${perls[*]} /usr/bin/perl" -- ${cur}
等同于 compgen -Wperl的一perl的二的/ usr / bin中/ perl的 - $ {CUR}
,其中你想要做什么。另一方面,
is equivalent to compgen -W "perl-one perl-two /usr/bin/perl" -- ${cur}
, which does what you want. On the other hand,
perls=(perl-one perl-two)
compgen -W "${perls[@]} /usr/bin/perl" -- ${cur}
等同于 compgen -W的perl-一perl的两的/ usr / bin中/ perl的 - $ {CUR}
,这完全是胡说八道: Perl的一是唯一的补偿字贴在-W标志,第一个真正的说法 - 这compgen将作为完成字符串 - 是perl的二的/ usr / bin中/ perl的。我期望compgen抱怨说,它被赋予了额外的参数( - 和任何在$ CUR),但显然它只是忽略它们。
is equivalent to compgen -W "perl-one" "perl-two /usr/bin/perl" -- ${cur}
, which is complete nonsense: "perl-one" is the only comp-word attached to the -W flag, and the first real argument -- which compgen will take as the string to be completed -- is "perl-two /usr/bin/perl". I'd expect compgen to complain that it's been given extra arguments ("--" and whatever's in $cur), but apparently it just ignores them.
这篇关于一个混淆$ {数组[*]}与$ {数组[@]}在完成击的情况下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!