Mic*_*aël 4 zsh array arithmetic
ZSH 手册 ( zshparam(1)) 写道:
Array Subscripts
Individual elements of an array may be selected using a subscript. A
subscript of the form `[exp]' selects the single element exp, where
exp is an arithmetic expression which will be subject to arithmetic
expansion as if it were surrounded by `$((...))'.
Run Code Online (Sandbox Code Playgroud)
然而,这很快就失败了:
mc% arr=(a b c d e)
mc% echo $arr[$#arr]
e
mc% echo $arr[$(($#arr))]
e
mc% echo $arr[$(($#arr - 1))]
d
mc% echo $arr[$#arr - 1]
zsh: invalid subscript
Run Code Online (Sandbox Code Playgroud)
问题:为什么?有哪些例外?
注意:这个问题源于don_crissti 在那里的回答,他们建议$arr[RANDOM % $#arr + 1]访问随机元素,但这会引发上述错误。
从技术上讲,任何表达式都可以作为下标出现。问题是让解析器把你想要的放在下标中。一些字符,包括空格,永远不会出现。只有单词组成字符可以是下标的一部分,因为下标是单词的一部分。
mc% echo $arr[ 1]
zsh: invalid subscript
mc% echo $arr[1 ]
zsh: invalid subscript
mc% echo $arr[$#arr - 1]
zsh: invalid subscript
mc% echo $arr[$#arr-1]
d
Run Code Online (Sandbox Code Playgroud)
下标解析器在第一个无效字符处停止,并且在 zsh 甚至检查终止右括号之前触发“无效下标”错误。
mc% echo $arr[ 1
zsh: invalid subscript
Run Code Online (Sandbox Code Playgroud)
在 中echo $arr[ 1],空格后面的部分实际上被认为是一个单独的词:echo将接收由$arr[and扩展产生的两个参数1],除了 zsh 由于解析失败而没有开始执行任何命令。在某些情况下,您可以判断出您可能认为是算术表达式的一部分的内容实际上并未被解析为这样,例如:
mc% echo $arr[1<<2]
heredoc> << is a heredoc operator, not part of the subscript.
heredoc> 2]
zsh: invalid subscript
Run Code Online (Sandbox Code Playgroud)
非单词组成字符当然可以作为嵌套扩展(例如算术表达式或命令替换)的一部分潜入。
mc% echo $arr[$[1&3]]
a
mc% echo $arr[`echo "1 + 2"`]
c
Run Code Online (Sandbox Code Playgroud)
如果参数扩展在双引号中,则任何字符(除了平衡的右括号或结束引号)都将成为下标的一部分。那是因为在双引号内,任何字符实际上都是单词组成字符。同样,如果参数扩展使用大括号,zsh 会}在查找]下标的右方括号之前查找参数扩展的右方括号,因此非单词组成字符确实会进入下标。
mc% echo "$arr[$#arr - 1]"
d
mc% echo ${arr[$#arr - 1]}
d
Run Code Online (Sandbox Code Playgroud)
如果您想深入了解细节,相关函数是parse_subscript,从 调用getindex。