在ZSH中,哪些算术表达式可以作为数组下标出现?

在ZSH中,哪些算术表达式可以作为数组下标出现?

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 `$((...))'.

然而,这很快就会失败:

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

问题:为什么?有哪些例外情况?

笔记:这个问题源于那里有 don_crissti 的回答,他们建议$arr[RANDOM % $#arr + 1]访问随机元素,但这会引发上述错误。

答案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

下标解析器在第一个无效字符处停止,并且在 zsh 检查终止右括号之前触发“无效下标”错误。

mc% echo $arr[ 1  
zsh: invalid subscript

在 中echo $arr[ 1],空格后面的部分实际上被认为是一个单独的单词:将接收由和echo扩展产生的两个参数,但 zsh 由于解析失败而不会开始执行任何命令。在某些情况下,您可以看出您可能认为是算术表达式一部分的内容实际上并未被如此解析,例如:$arr[1]

mc% echo $arr[1<<2]   
heredoc> << is a heredoc operator, not part of the subscript.
heredoc> 2]
zsh: invalid subscript

非单词组成的字符当然可以作为嵌套扩展的一部分潜入,例如算术表达式或命令替换。

mc% echo $arr[$[1&3]] 
a
mc% echo $arr[`echo "1 + 2"`]  
c

如果参数扩展使用双引号,则任何字符(除了平衡的右括号或结束引号之外)都会成为下标的一部分。这是因为在双引号内,任何字符实际上都是单词组成字符。同样,如果参数扩展使用大括号,则 zsh}在查找下标的右括号之前先查找参数扩展的右大括号],因此非单词组成字符确实会进入下标。

mc% echo "$arr[$#arr - 1]"
d
mc% echo ${arr[$#arr - 1]}
d

如果您想深入了解具体细节,相关函数是parse_subscript, 调用自getindex

相关内容