有没有办法用 bash 读取数组的最后一个元素?

3ks*_*stc 98 bash array

如果我有一个包含 5 个元素的数组,例如:

[a][b][c][d][e]
Run Code Online (Sandbox Code Playgroud)

使用echo ${myarray[4]}我可以看到它包含什么。

但是如果我不知道给定数组中的元素数量怎么办?有没有办法读取未知长度数组的最后一个元素?即任何数组从右到左读取的第一个元素?

我想知道如何在 bash 中做到这一点。

Mic*_*mer 132

从 bash 4.2 开始,您可以只使用负索引 ${myarray[-1]}来获取最后一个元素。你可以对倒数第二个做同样的事情,依此类推;在 Bash 中:

如果用于引用索引数组元素的下标计算结果为小于零的数字,则将其解释为相对于大于数组最大索引的数字,因此负索引从数组末尾开始计数,并且-1 的索引指的是最后一个元素。

这同样适用于赋值。当它说“表达”时,它的意思是表达;您可以在那里写入任何算术表达式来计算索引,包括${#myarray[@]}${myarray[${#myarray[@]} - 1]}早期版本一样使用数组长度进行计算的表达式。

  • 负索引仅适用于 bash 4.3 及更高版本。 (31认同)
  • Mac OS X 包含的 Bash 版本至少从 v10.11.5 开始只有 3.2,所以这在 Mac 上不起作用。 (11认同)
  • 但是,使用`zsh`,默认情况下数组是1-indexed,不像`bash` 和`ksh` 是0-indexed。 (5认同)
  • 你也可以在 `ksh` 和 `zsh` 中做到这一点。 (2认同)
  • 是的当然; 这个问题的简短答案不会改变,但由于提到了长形式,我认为有必要指出那里的行为差异。 (2认同)
  • 请注意,对于`$@` 需要不同的语法:`${@:(-1)}`。 (2认同)

Joh*_*024 57

现代 bash(v4.1 或更高版本)

您可以读取 index 处的最后一个元素-1

$ a=(a b c d e f)
$ echo ${a[-1]}
f
Run Code Online (Sandbox Code Playgroud)

支持使用从bash 版本 4.1-alpha 开始的负索引从末尾访问数字索引数组。

较旧的 bash(v4.0 或更早版本)

您必须从中获取数组长度${#a[@]},然后减去一个以获取最后一个元素:

$ echo ${a[${#a[@]}-1]}
f
Run Code Online (Sandbox Code Playgroud)

由于 bash 将数组下标视为算术表达式,因此不需要额外的符号(例如$((...)))来强制算术求值。


cuo*_*glm 19

bash数组赋值、引用、负索引取消设置仅在 bash 4.3 中添加。使用旧版本的bash,您可以在索引中使用表达式array[${#array[@]-1}]

另一种方式,也适用于旧版本bash(bash 3.0 或更高版本):

$ a=([a] [b] [c] [d] [e])
$ printf %s\\n "${a[@]:(-1)}"
[e]
Run Code Online (Sandbox Code Playgroud)

或者:

$ printf %s\\n "${a[@]: -1}"
[e]
Run Code Online (Sandbox Code Playgroud)

使用负偏移量时,需要将:with分开,-以免与:-扩展混淆。


ImH*_*ere 5

大批

bash 中最古老的替代方案(自 bash 3.0+ 起)是:

$ a=(aa bb cc dd ee)
$ echo "${a[@]:(-1)}   ${a[@]: -1}   ${a[@]:(~0)}   ${a[@]:~0}"
ee   ee   ee   ee
Run Code Online (Sandbox Code Playgroud)

需要空格以避免将:后跟减号解释-"${var:-abc}"(使用默认值)的扩展。

~是一个算术位否定(相当于一个的补码或翻转所有位)。从人bash:

算术评估

      ! ~         logical and bitwise negation  
Run Code Online (Sandbox Code Playgroud)

由于 bash-4.2+ 还:

$ echo "${a[-1]}   ${a[(~0)]}"
ee   ee
Run Code Online (Sandbox Code Playgroud)

由于 bash 5.0+ 还:

$ echo "${a[~0]}"
ee
Run Code Online (Sandbox Code Playgroud)

对于所有 bash 版本(较旧的 bash):

$ echo "${a[   ${#a[@]}-1   ]}"    # spaces added **only** for readability
ee
Run Code Online (Sandbox Code Playgroud)

@

对于位置参数(自 bash 2.01 起):

$ set aa bb cc dd ee
$ echo "${@:(-1)} ${@:~0} ${@: -1} ${@:$#}   ${!#}"
ee ee ee   ee
Run Code Online (Sandbox Code Playgroud)

所有 shell 的便携解决方案是使用 eval:

eval printf '"%s\n"' \"\${$#}\"
Run Code Online (Sandbox Code Playgroud)