Di ZSH, ekspresi aritmatika apa yang dapat muncul sebagai subskrip array?
Manual ZSH ( zshparam(1)
) berbunyi:
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 `$((...))'.
Namun, ini dengan cepat gagal:
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
Pertanyaan: Mengapa, dan apa pengecualiannya?
Catatan: pertanyaan ini berasal dari jawaban don_crissti di sana , di mana mereka menyarankan $arr[RANDOM % $#arr + 1]
untuk mengakses elemen acak, tetapi ini memunculkan kesalahan di atas.
Jawaban
Secara teknis, ekspresi apa pun bisa muncul sebagai subskrip. Masalahnya adalah membuat parser memasukkan apa yang Anda inginkan ke dalam subskrip. Beberapa karakter, termasuk spasi, tidak pernah berhasil. Hanya karakter penyusun kata yang dapat menjadi bagian dari subskrip, karena subskrip adalah bagian dari sebuah kata.
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
Pengurai subskrip berhenti pada karakter pertama yang tidak valid, dan kesalahan "subskrip tidak valid" dipicu sebelum zsh bahkan memeriksa kurung tutup penutup.
mc% echo $arr[ 1
zsh: invalid subscript
Dalam echo $arr[ 1]
, bagian setelah spasi sebenarnya dianggap sebagai kata terpisah: echo
akan menerima dua argumen yang dihasilkan dari perluasan $arr[
dan 1]
, kecuali bahwa zsh tidak mulai menjalankan perintah apa pun karena kegagalan penguraian. Ada beberapa kasus di mana Anda dapat mengetahui bahwa apa yang mungkin Anda anggap sebagai bagian dari ekspresi aritmatika ternyata tidak diurai seperti itu, misalnya:
mc% echo $arr[1<<2]
heredoc> << is a heredoc operator, not part of the subscript.
heredoc> 2]
zsh: invalid subscript
Karakter non-konstituen-kata tentu saja dapat menyelinap sebagai bagian dari perluasan bersarang seperti ekspresi aritmatika atau substitusi perintah.
mc% echo $arr[$[1&3]]
a
mc% echo $arr[`echo "1 + 2"`]
c
Jika perluasan parameter dalam tanda kutip ganda, karakter apa pun (selain tanda kurung tutup yang seimbang atau tanda kutip akhir) akan menjadi bagian dari subskrip. Itu karena di dalam tanda kutip ganda, setiap karakter secara efektif merupakan karakter penyusun kata. Demikian juga, jika perluasan parameter menggunakan tanda kurung kurawal, zsh mencari kurung kurawal tutup }
untuk perluasan parameter sebelum mencari kurung tutup ]
untuk subskrip, sehingga karakter non-konstituen kata membuatnya menjadi subskrip.
mc% echo "$arr[$#arr - 1]" d mc% echo ${arr[$#arr - 1]}
d
Jika Anda ingin menyelami detailnya, fungsi yang relevan parse_subscriptdipanggil dari getindex.