Apakah ada cara ringkas pengujian untuk dukungan array oleh shell Bourne-like lokal di baris perintah?
Ini selalu mungkin:
$ arr=(0 1 2 3);if [ "${arr[2]}" != 2 ];then echo "No array support";fi
atau pengujian untuk $SHELL
dan versi shell:
$ eval $(echo "$SHELL --version") | grep version
dan kemudian membaca halaman manual, dengan asumsi saya memiliki akses ke sana. (Bahkan di sana, menulis dari /bin/bash
, saya mengasumsikan bahwa semua shell Bourne-like mengakui opsi panjang --version
, ketika itu istirahat untuk ksh misalnya .)
Saya mencari tes sederhana yang dapat dilakukan tanpa pengawasan dan dimasukkan dalam bagian Penggunaan di awal skrip atau bahkan sebelum menyebutnya.
shell-script
shell
array
Cbhihe
sumber
sumber
csh
bukan shell bourne.tcsh
juga bukan salah satu (csh
dengan beberapa bug diperbaiki)$SHELL
adalah shell yang disukai pengguna, seperti$EDITOR
editor teks pilihannya. Ini tidak ada hubungannya dengan shell yang sedang berjalan.eval
menggunakan output$SHELL --version
sebagai kode shell tidak masuk akal.Jawaban:
Dengan asumsi Anda ingin membatasi untuk Bourne-seperti kerang (banyak kerang lainnya seperti
csh
,tcsh
,rc
,es
ataufish
array dukungan tetapi menulis naskah kompatibel pada saat yang sama untuk Bourne-seperti kerang dan mereka adalah rumit dan umumnya sia-sia karena mereka interpreter untuk benar-benar berbeda dan bahasa yang tidak kompatibel), perhatikan bahwa ada perbedaan signifikan antara implementasi.Shell Bourne like yang mendukung array adalah:
ksh88
(itulah array implementasi pertama, ksh88 masih ditemukanksh
pada kebanyakan Unite komersial tradisional yang juga menjadi dasar untuksh
)set -A array foo bar
atauset -A array -- "$var" ...
jika Anda tidak dapat menjamin bahwa$var
tidak akan mulai dengan-
atau+
.0
.a[1]=value
.a[5]=foo
akan bekerja bahkan jikaa[0,1,2,3,4]
tidak disetel dan akan membiarkannya tidak disetel.${a[5]}
untuk mengakses elemen indice 5 (belum tentu elemen ke-6 jika array jarang). The5
bisa ada ekspresi aritmatika.${#a[@]}
adalah jumlah elemen yang ditugaskan dalam array (bukan indice yang ditugaskan terbesar).[[ -n "${a[i]+set}" ]]
).$a
sama dengan${a[0]}
. Itu adalah array yang entah bagaimana memperluas variabel skalar dengan memberi mereka nilai tambahan.pdksh
dan turunannya (itulah dasar untukksh
dan terkadangsh
beberapa BSD dan merupakan satu-satunya implementasi ksh opensource sebelum sumber ksh93 dibebaskan):Paling suka
ksh88
tapi perhatikan:set -A array -- foo bar
, (--
tidak diperlukan di sana).${#a[@]}
adalah salah satu plus indice dari indice ditugaskan terbesar. (a[1000]=1; echo "${#a[@]}"
output 1001 meskipun array hanya memiliki satu elemen.mksh
memiliki operator beberapa tambahan terinspirasi daribash
,ksh93
atauzsh
seperti tugas a laa=(x y)
,a+=(z)
,${!a[@]}
untuk mendapatkan daftar indeks ditugaskan.zsh
.zsh
array umumnya dirancang lebih baik dan mengambil yang terbaik dariksh
dancsh
array. Mereka miripksh
tetapi dengan perbedaan signifikan:ksh
emulasi), itu konsisten dengan array Bourne (parameter posisi $ @, yangzsh
juga mengekspos sebagai array $ argv) dancsh
array.$a
tidak sama dengan${a[0]}
tetapi memperluas ke elemen array yang tidak kosong ("${a[@]}"
untuk semua elemen seperti diksh
).a[5]=1
berfungsi tetapi menetapkan semua elemen dari 1 hingga 4 string kosong jika tidak ditetapkan. Jadi${#a[@]}
(sama seperti${#a}
yang di ksh adalah ukuran elemen indice 0) adalah jumlah elemen dalam array dan indice ditugaskan terbesar.a=(x y)
.set -A a x y
juga berfungsi, tetapiset -A a -- x y
tidak didukung kecuali dalam emulasi ksh (--
tidak diperlukan dalam emulasi zsh).ksh93
. (di sini menjelaskan versi terbaru).ksh93
, eksperimental lama dianggap sekarang dapat ditemukan di semakin banyak sistem sekarang yang telah dirilis sebagai FOSS. Sebagai contoh, itu adalah/bin/sh
(di mana ia menggantikan Bourne shell,/usr/xpg4/bin/sh
, POSIX shell masih didasarkan padaksh88
) danksh
dariSolaris 11
. Susunannya memperpanjang dan meningkatkan ksh88.a=(x y)
dapat digunakan untuk mendefinisikan array, tetapi karenaa=(...)
juga digunakan untuk mendefinisikan variabel gabungan (a=(foo=bar bar=baz)
),a=()
bersifat mendua dan mendeklarasikan variabel gabungan, bukan array.a=((0 1) (0 2))
) dan elemen array juga bisa menjadi variabel majemuk (a=((a b) (c=d d=f)); echo "${a[1].c}"
).a=([2]=foo [5]=bar)
sintaks dapat digunakan untuk mendefinisikan array jarang sekaligus.zsh
, tetapi sejumlah besar operator didukung juga untuk memanipulasi array."${!a[@]}"
untuk mengambil daftar indeks array.bash
.bash
adalah shell dari proyek GNU. Ini digunakan sepertish
pada versi OS / X terbaru dan beberapa distribusi GNU / Linux.bash
array sebagian besar meniruksh88
yang dengan beberapa fiturksh93
danzsh
.a=(x y)
didukung.set -A a x y
tidak didukung.a=()
membuat array kosong (tidak ada variabel majemuk dibash
)."${!a[@]}"
untuk daftar indeks.a=([foo]=bar)
sintaks yang didukung serta beberapa lainnya dariksh93
danzsh
.bash
versi terbaru juga mendukung array asosiatif sebagai tipe terpisah.yash
. Ini adalah implementasi POSIX sh yang relatif baru, bersih, multi-byte yang disadari. Tidak digunakan secara luas. Arraynya adalah API bersih lain yang mirip denganzsh
a=(var value)
array
builtinarray -s a 5 value
untuk memodifikasi elemen ke- 5 akan gagal jika elemen itu tidak ditetapkan sebelumnya.${a[#]}
,${#a[@]}
menjadi ukuran elemen sebagai daftar.a=("$a")
mendefinisikan ulang variabel skalar sebagai array sebelum Anda dapat menambah atau memodifikasi elemen.sh
.Jadi, dari situ Anda dapat melihat bahwa mendeteksi dukungan array, yang dapat Anda lakukan dengan:
tidak cukup untuk dapat menggunakan array itu. Anda perlu mendefinisikan perintah wrapper untuk menetapkan array sebagai elemen keseluruhan dan individual, dan pastikan Anda tidak mencoba membuat array jarang.
Suka
Dan kemudian Anda mengakses elemen array dengan
"${a[$first_indice+n]}"
, seluruh daftar dengan"${a[@]}"
dan menggunakan fungsi wrapper (array_elements
,set_array
,set_array_element
) untuk mendapatkan jumlah elemen array (dalam$REPLY
), mengatur array sebagai keseluruhan atau menetapkan unsur-unsur individu.Mungkin tidak sepadan dengan usaha. Saya akan menggunakan
perl
atau batasan untuk Bourne / POSIX shell array yang:"$@"
.Jika maksudnya untuk memiliki beberapa file yang akan dipasok oleh shell interaktif pengguna untuk mendefinisikan fungsi yang secara internal menggunakan array, berikut adalah beberapa catatan yang mungkin berguna.
Anda dapat mengonfigurasi
zsh
array menjadi lebih sepertiksh
array di lingkup lokal (dalam fungsi atau fungsi anonim).Anda juga dapat meniru
ksh
(meningkatkan kompatibilitas denganksh
untuk array dan beberapa area lainnya) dengan:Dengan mengingat hal itu dan Anda bersedia melepaskan dukungan untuk
yash
danksh88
dan versipdksh
turunan yang lebih lama, dan selama Anda tidak mencoba membuat array jarang, Anda harus dapat menggunakan:a[0]=foo
a=(foo bar)
(tapi tidaka=()
)"${a[#]}"
,"${a[@]}"
,"${a[0]}"
dalam fungsi-fungsi yang memiliki
emulate -L ksh
, sementarazsh
pengguna masih menggunakan array nya biasanya dengan cara zsh.sumber
Anda dapat menggunakan
eval
untuk mencoba sintaks array:sumber
ksh88
mendukung array tetapi tidaka=()
. Diksh93
,a=()
mendeklarasikan variabel gabungan, bukan array kecuali variabel tersebut telah dideklarasikan sebagai array sebelumnya.yash
, Anda tidak melakukana[5]=1
tetapiarray -s a 5 1
ksh93
membuat saya terkejut, maukah Anda memberi saya bagian dari dokumentasi tentang hal itu. Saya menambahkan1
ke array untuk membuatnya berfungsi.