Untuk bash , ini sedikit hack (meskipun didokumentasikan): upaya typesetuntuk menghapus atribut "array":
$ typeset +a BASH_VERSINFO
bash: typeset: BASH_VERSINFO: cannot destroy array variables in this way
echo $?
1
(Anda tidak dapat melakukan ini di zsh, ini memungkinkan Anda untuk mengubah array menjadi skalar, di bashdalamnya secara eksplisit dilarang.)
Begitu:
typeset +A myvariable 2>/dev/null || echo is assoc-array
typeset +a myvariable 2>/dev/null || echo is array
Atau dalam suatu fungsi, mencatat peringatan pada akhirnya:
function typeof() {
local _myvar="$1"
if ! typeset -p $_myvar 2>/dev/null ; then
echo no-such
elif ! typeset -g +A $_myvar 2>/dev/null ; then
echo is-assoc-array
elif ! typeset -g +a $_myvar 2>/dev/null; then
echo is-array
else
echo scalar
fi
}
Perhatikan penggunaan typeset -g(bash-4.2 atau yang lebih baru), ini diperlukan dalam suatu fungsi agar typeset(syn. declare) Tidak berfungsi seperti localdan merusak nilai yang Anda coba periksa. Ini juga tidak menangani fungsi "variabel" jenis, Anda dapat menambahkan tes cabang lain menggunakan typeset -fjika diperlukan.
Opsi lain (hampir selesai) adalah menggunakan ini:
${!name[*]}
If name is an array variable, expands to the list
of array indices (keys) assigned in name. If name
is not an array, expands to 0 if name is set and
null otherwise. When @ is used and the expansion
appears within double quotes, each key expands to a
separate word.
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:
if [[ ${!BASH_VERSINFO[*]} == '' ]]; then
echo no-such
elif [[ ${!BASH_VERSINFO[*]} == '0' ]]; then
echo not-array
elif [[ ${!BASH_VERSINFO[*]} != '0' ]];
echo is-array
fi
Saya telah menggunakan variasi sebelumnya:
while read _line; do
if [[ $_line =~ ^"declare -a" ]]; then
...
fi
done < <( declare -p )
ini juga membutuhkan subkulit.
Satu lagi teknik yang mungkin bermanfaat adalah compgen:
compgen -A arrayvar
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)