一个混淆$ {数组[*]}与$ {数组[@]}在完成击的情况下 [英] A confusion about ${array[*]} versus ${array[@]} in the context of a Bash completion

查看:126
本文介绍了一个混淆$ {数组[*]}与$ {数组[@]}在完成击的情况下的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在刺伤编写完成猛砸,第一次,我有点困惑约提领猛砸阵列的两种方式( $ {数组[@]} $ {数组[*]} )。

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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆