Di Bourne like shell yang mendukung variabel array, kita bisa menggunakan beberapa parsing untuk memeriksa apakah variabel adalah array.
Semua perintah di bawah ini dijalankan setelah dijalankan a=(1 2 3)
.
zsh
:
$ declare -p a
typeset -a a
a=( 1 2 3 )
bash
:
$ declare -p a
declare -a a='([0]="1" [1]="2" [2]="3")'
ksh93
:
$ typeset -p a
typeset -a a=(1 2 3)
pdksh
dan turunannya:
$ typeset -p a
set -A a
typeset a[0]=1
typeset a[1]=2
typeset a[2]=3
yash
:
$ typeset -p a
a=('1' '2' '3')
typeset a
Contoh dalam bash
:
if declare -p var 2>/dev/null | grep -q 'declare -a'; then
echo array variable
fi
Pendekatan ini terlalu banyak bekerja dan perlu menelurkan subkulit. Menggunakan shell builtin lain seperti =~
dalam [[ ... ]]
tidak perlu subkulit, tetapi masih terlalu rumit.
Apakah ada cara yang lebih mudah untuk menyelesaikan tugas ini?
Jawaban:
Saya tidak berpikir Anda bisa, dan saya tidak berpikir itu benar-benar membuat perbedaan.
Itu melakukan hal yang sama di salah satu
ksh93
danbash
. Sepertinya semua variabel adalah array di shell tersebut, atau setidaknya variabel biasa yang belum diberi atribut khusus, tetapi saya tidak memeriksa banyak hal.The
bash
pembicaraan pengguna tentang perilaku yang berbeda untuk berbagai versus variabel string ketika menggunakan+=
tugas, tapi setelah itu pagar dan menyatakan bahwa array hanya berperilaku berbeda dalam senyawa konteks tugas.Ini juga menyatakan bahwa variabel dianggap sebagai array jika ada subskrip yang diberi nilai - dan secara eksplisit menyertakan kemungkinan null-string. Di atas Anda dapat melihat bahwa penugasan reguler pasti menghasilkan subskrip yang ditugaskan - dan saya rasa semuanya adalah array.
Secara praktis, mungkin Anda dapat menggunakan:
... untuk menunjukkan dengan jelas variabel set yang hanya ditugaskan satu subskrip nilai 0.
sumber
${a[1]-not array}
dapat melakukan tugas, bukan?bash
manual: Sebuah variabel array dianggap disetel jika sebuah subskrip telah diberi nilai. String nol adalah nilai yang valid. Jika ada subscript yang diberikan array per spec. Dalam latihan, juga tidak, karena Anda bisa melakukannyaa[5]=x
. Saya kira[ 1 -eq "${#a[@]}" ] && [ -n "${a[0]+1}" ]
bisa bekerja.Jadi Anda ingin hanya bagian tengah
declare -p
tanpa sampah di sekitarnya?Anda dapat menulis makro seperti:
sehingga Anda dapat melakukan:
(Fungsi belaka tidak akan berfungsi jika Anda ingin menggunakannya pada variabel fungsi-lokal).
Dengan alias
sumber
alias vartype="$VARTYPE"
... atau tidak mendefinisikan$VARTYPE
sama sekali - itu harus bekerja, kan? Anda hanya perlu memasukkanshopt
halbash
itu karena tidak sesuai dengan spesifikasi mengenaialias
ekspansi skrip.Dalam zsh
sumber
echo ${(t)var}
lebih sederhana. Terima kasih untuk ini.Untuk menguji var variabel, dengan
Adalah mungkin untuk menguji apakah ada lebih dari satu indeks array:
Jika nilai indeks pertama bukan nol:
Satu-satunya kebingungan adalah ketika hanya ada satu nilai indeks dan nilai itu nol (atau satu).
Untuk kondisi itu, dimungkinkan untuk menggunakan efek samping dari mencoba menghapus elemen array dari variabel yang bukan array:
Ini berfungsi dengan benar untuk bash:
Untuk zsh, indeks mungkin harus 1 (kecuali mode yang kompatibel aktif).
Sub-shell diperlukan untuk menghindari efek samping dari menghapus indeks 0 dari var.
Saya tidak menemukan cara untuk membuatnya bekerja di ksh.
Edit 1
Fungsi ini hanya berfungsi di bash4.2 +
Edit 2
Ini juga berfungsi hanya untuk bash4.2 +
Catatan: Ini akan memberikan positif palsu jika var berisi string yang diuji.
sumber
( unset "var[0]" 2>/dev/null; ) && echo "var is an array."
dengan benar melaporkan var adalah array ketika var telah diatur kevar=()
array dengan nol elemen. Kerjanya persis sama dengan menyatakan.grep -E
alih-alihgrep -P
untuk menghindari ketergantungan pada GNU grep.-a
, seperti ini:declare -airl var='()'
. Karenanya tes grep akan bekerja .Untuk bash , ini sedikit hack (meskipun didokumentasikan): upaya
typeset
untuk menghapus atribut "array":(Anda tidak dapat melakukan ini di
zsh
, ini memungkinkan Anda untuk mengubah array menjadi skalar, dibash
dalamnya secara eksplisit dilarang.)Begitu:
Atau dalam suatu fungsi, mencatat peringatan pada akhirnya:
Perhatikan penggunaan
typeset -g
(bash-4.2 atau yang lebih baru), ini diperlukan dalam suatu fungsi agartypeset
(syn.declare
) Tidak berfungsi sepertilocal
dan merusak nilai yang Anda coba periksa. Ini juga tidak menangani fungsi "variabel" jenis, Anda dapat menambahkan tes cabang lain menggunakantypeset -f
jika diperlukan.Opsi lain (hampir selesai) adalah menggunakan ini:
Namun ada satu masalah, array dengan satu subskrip 0 cocok dengan dua kondisi di atas. Ini adalah sesuatu yang mikeserv juga referensi, bash benar-benar tidak memiliki perbedaan yang sulit, dan beberapa di antaranya (jika Anda memeriksa Changelog) dapat disalahkan pada ksh dan kompatibel dengan bagaimana
${name[*]}
atau${name[@]}
berperilaku pada non-array.Jadi solusi parsial adalah:
Saya telah menggunakan variasi sebelumnya:
ini juga membutuhkan subkulit.
Satu lagi teknik yang mungkin bermanfaat adalah
compgen
:Ini akan mencantumkan semua array yang diindeks, namun array asosiatif tidak ditangani secara khusus (hingga bash-4.4) dan muncul sebagai variabel reguler (
compgen -A variable
)sumber
typeset +a
juga melaporkan kesalahan dalam ksh. Tapi tidak dalam zsh.Jawaban singkat:
Untuk dua shell yang memperkenalkan notasi ini (
bash
danksh93
) variabel skalar hanyalah sebuah array dengan elemen tunggal .Tidak perlu deklarasi khusus untuk membuat array. Hanya tugas sudah cukup, dan tugas polos
var=value
identik denganvar[0]=value
.sumber
bash -c 'unset var; var=foo; typeset -p var'
. Apakah bash answer melaporkan array (membutuhkan -a) ?. Sekarang bandingkan dengan:bash -c 'unset var; var[12]=foo; typeset -p var'
. Mengapa ada perbedaan? A: Shell mempertahankan (baik atau buruk) gagasan yang vars adalah skalar atau array. Shell ksh menggabungkan kedua konsep menjadi satu.yash's
array
builtin memiliki beberapa opsi yang hanya berfungsi dengan variabel array. Contoh:-d
opsi akan melaporkan kesalahan pada variabel non-array:Jadi kita bisa melakukan sesuatu seperti ini:
Pendekatan ini tidak akan berfungsi jika variabel array dibaca hanya . Mencoba mengubah variabel hanya baca yang mengarah ke kesalahan:
sumber
sumber