W ZSH, jakie wyrażenia arytmetyczne mogą pojawić się jako indeks tablicy?
Instrukcja ZSH ( zshparam(1)
) brzmi:
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 `$((...))'.
Jednak szybko się to nie udaje:
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
Pytanie: Dlaczego i jakie są wyjątki?
Uwaga: to pytanie wywodzi się z odpowiedzi don_crissti tam , gdzie sugerują $arr[RANDOM % $#arr + 1]
dostęp do losowego elementu, ale powoduje to powyższy błąd.
Odpowiedzi
Z technicznego punktu widzenia każde wyrażenie może pojawić się jako indeks dolny. Problem polega na tym, że parser umieści to, co chcesz, w indeksie dolnym. Niektórym postaciom, w tym spacjom, nigdy się to nie udaje. Tylko znaki składowe słowa mogą być częścią indeksu dolnego, ponieważ indeks dolny jest częścią słowa.
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
Parser indeksu dolnego zatrzymuje się na pierwszym nieprawidłowym znaku i wyzwalany jest błąd „nieprawidłowego indeksu”, zanim zsh nawet sprawdzi kończący nawias zamykający.
mc% echo $arr[ 1
zsh: invalid subscript
W echo $arr[ 1]
programie część po spacji jest faktycznie traktowana jako osobne słowo: echo
otrzymywałaby dwa argumenty wynikające z rozwinięcia $arr[
i 1]
, z tym że zsh nie rozpoczyna wykonywania żadnego polecenia z powodu błędu parsowania. Jest kilka przypadków, w których możesz stwierdzić, że to, o czym możesz pomyśleć jako część wyrażenia arytmetycznego, w rzeczywistości nie jest analizowane jako takie, na przykład:
mc% echo $arr[1<<2]
heredoc> << is a heredoc operator, not part of the subscript.
heredoc> 2]
zsh: invalid subscript
Znaki niebędące składnikami słowa mogą oczywiście wkraść się jako część zagnieżdżonej interpretacji, takiej jak wyrażenie arytmetyczne lub podstawienie polecenia.
mc% echo $arr[$[1&3]]
a
mc% echo $arr[`echo "1 + 2"`]
c
Jeśli interpretacja parametrów znajduje się w cudzysłowach, każdy znak (poza zrównoważonym nawiasem zamykającym lub końcowym cudzysłowem) przechodzi jako część indeksu dolnego. Dzieje się tak, ponieważ wewnątrz podwójnych cudzysłowów każdy znak jest w rzeczywistości znakiem składowym słowa. Podobnie, jeśli interpretacja parametrów używa nawiasów klamrowych, zsh szuka nawiasu zamykającego }
dla interpretacji parametrów, zanim szuka nawiasu zamykającego ]
dla indeksu dolnego, a więc znaki niebędące składnikami słowa trafiają do indeksu dolnego.
mc% echo "$arr[$#arr - 1]" d mc% echo ${arr[$#arr - 1]}
d
Jeśli chcesz zagłębić się w szczegóły, odpowiednia funkcja jest parse_subscriptwywoływana z getindex.