获取数组的第一个索引

时间:2017-12-24 19:14:05

标签: arrays linux bash

我有一个未从0索引的数组:

arr=([2]=aaa bbb ccc ddd)

我需要获取数组的第一个索引。有很多事情我尝试过并且有效:

for index in "${!arr[@]}"; do
    first_index=$index
    break
done
first_index=$(awk '{ print $1 }' <<< "${!arr[@]}")
first_index=$(cut -d' ' -f1 <<< "${!arr[@]}")
first_index=${!arr[@]}
first_index=${first_index%% *}
ind=("${!arr[@]}")
first_index=${ind[@]:0:1}

真正想要工作的内容:

${!arr[@]:0:1}

鉴于此语法对数组${arr[@]:0:1}的效果非常好并且非常干净:

  1. 是否有类似的,更清晰的方法为索引执行此操作,没有外部工具,临时数组,临时变量,循环等?我的尝试似乎使这么简单的任务过于复杂
  2. ${!arr[@]:0:1}实际发生了什么?

1 个答案:

答案 0 :(得分:3)

  

我的尝试似乎使这么简单的任务过于复杂化

这个任务可能看起来很简单,但可能不是一个常见的用例,因此没有语法上的容易,特别是如果你可以使用其他内置功能来实现它。

你有很多选择,还有一个:

put_first_index_in () {
    printf -v "${1?}" "%s" "${2?}"
}

put_first_index_in first_index "${!arr[@]}"
  

$ {!arr [@]:0:1}实际发生了什么?

Indirect variable expansion

  

如果参数的第一个字符是感叹号(!),   而参数不是 nameref ,它引入了一个变量级别   间接。 Bash使用从其余部分形成的变量的值   参数作为变量的名称;那么这个变量就是   扩展,该值用于替换的其余部分,   而不是参数本身的值。这被称为   indirect expansion

!作为第一个字符,支持三种可能的事项:${!parameter}(上面给出的间接扩展),${!prefix*}${!prefix@}(扩展为变量名匹配) prefix)和${!name[*]}${!name[@]}(扩展为name数组的索引)。

文档建议只有${!parameter}支持进一步替换,因为它只是为此提及而不是为其他人提及。所以bash尝试执行以下操作:

  1. 展开arr[@]
  2. 对从(1)
  3. 获得的字符串应用间接扩展
  4. 从间接扩展
  5. 获取的字符串中获取0:1子字符串

    由于不是标识符中的有效字符,我们会收到该错误:

    $ foo=SHELL
    $ echo ${!foo}
    /bin/zsh
    $ echo ${!foo:0:1}
    /
    $ foo="SHELL "
    $ echo ${!foo}
    bash: SHELL : bad substitution
    $ arr=([2]=SHELL bbb ccc ddd)
    $ echo ${!arr[@]:0:1}
    bash: SHELL bbb ccc ddd: bad substitution
    

    因此,这只适用于单个元素的数组,例如:

    $ arr=([2]=SHELL)
    

    正如所料:

    $ echo ${!arr[@]:0:1}
    /