【问题标题】:Getting first index of array获取数组的第一个索引
【发布时间】:2018-06-06 09:34:16
【问题描述】:

我有一个不是从 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} 中实际发生了什么?

【问题讨论】:

  • 循环是我使用的方法,顺便说一句。它很冗长,但比使用外部命令的尝试更有效率。如果您必须使用first_index=${!arr[@]} 方法,请将其改为[*],这样您就可以明确地请求字符串,而不是请求数组并将其强制转换为字符串。无论哪种情况,您都需要确保 IFS 的值是已知的。
  • ...index 也不需要,for first_index in "${!arr[@]}"; do break; done
  • (坦率地说,虽然——对“首选语法发生了什么?”这个问题的一个很好的答案需要跟踪subst.c 的一些非常多毛的部分;最好的人有能力在 bug-bash@gnu.org 上直播...虽然询问语法的问题应该首先通过 help-bash@gnu.org)。
  • arr=([2]=aaa bbb ccc ddd); index=(${!arr[@]}); echo ${index[0]}?

标签: arrays linux bash


【解决方案1】:

我的尝试似乎使如此简单的任务过于复杂

该任务可能看起来很简单,但可能不是一个常见的用例,因此没有语法糖可以让它变得简单,特别是如果您可以使用其他内置功能来完成它。

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

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

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

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

Indirect variable expansion:

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

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

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

  1. 展开arr[@]
  2. 对从 (1) 获得的字符串应用间接扩展
  3. 从间接展开得到的字符串中获取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}
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多