我有一个未从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}
非常有效并且非常干净:
${!arr[@]:0:1}
实际发生了什么?我的尝试似乎使这么简单的任务过于复杂
这个任务可能看起来很简单,但可能不是一个常见的用例,因此没有语法上的容易,特别是如果你可以使用其他内置功能来实现它。
你有很多选择,还有一个:
put_first_index_in () {
printf -v "${1?}" "%s" "${2?}"
}
put_first_index_in first_index "${!arr[@]}"
在$ {!arr [@]:0:1}中实际发生了什么?
如果参数的第一个字符是感叹号(
!
),并且参数不是nameref,则它引入了一个变量间接的级别。 Bash使用从参数的其余部分形成的变量的值作为变量的名称;然后展开此变量,并将该值用于替换的其余部分,而不是参数本身的值。这被称为indirect expansion
。
以!
为第一个字符,支持三种可能的东西:${!parameter}
(上面给出的间接扩展),${!prefix*}
,${!prefix@}
(扩展到与prefix
匹配的变量名称)和${!name[*]}
,${!name[@]}
(扩展到name
数组的索引)。
文件表明只有${!parameter}
支持进一步替换,因为它只是为此提及而不是为其他人提及。所以bash尝试执行以下操作:
arr[@]
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}
/