Untuk bash , ini sedikit hack (meskipun didokumentasikan): upaya typeset
untuk 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 bash
dalamnya 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 local
dan merusak nilai yang Anda coba periksa. Ini juga tidak menangani fungsi "variabel" jenis, Anda dapat menambahkan tes cabang lain menggunakan typeset -f
jika 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
)