İçin Bash , bu (belgelenmiş olsa) bir hack biraz var: kullanım girişimi typeset
"dizi" ayrıntısını kaldırmak için:
$ typeset +a BASH_VERSINFO
bash: typeset: BASH_VERSINFO: cannot destroy array variables in this way
echo $?
1
(Bunu yapamazsınız zsh
, bir diziyi skalere dönüştürmenize izin verir, bash
açıkça yasaktır.)
Yani:
typeset +A myvariable 2>/dev/null || echo is assoc-array
typeset +a myvariable 2>/dev/null || echo is array
Veya bir işlevde, sonunda uyarıları not edin:
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
}
Kullanımına dikkat typeset -g
(bash-4.2 veya üstü), bu şekilde bir işlev içinde gereklidir typeset
(syn. declare
) Gibi işi değil local
ve incelemek için çalışıyoruz değeri yenmek. Bu ayrıca işlev "değişken" türlerini işlemez, gerekirse başka bir dal testi ekleyebilirsiniz typeset -f
.
Başka bir (neredeyse tamamlanmış) seçenek bunu kullanmaktır:
${!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.
Yine de küçük bir sorun var, tek bir 0 aboneliğe sahip bir dizi yukarıdaki koşullardan ikisiyle eşleşiyor. Bu da mikeserv'in referans aldığı bir şeydir, bash gerçekten zor bir ayrımı yoktur ve bunların bir kısmı (Changelog'u kontrol ederseniz) ksh'a suçlanabilir ve bir dizide olmayan ${name[*]}
veya nasıl ${name[@]}
davranılacağı ile uyumlu olabilir .
Bir Yani kısmi bir çözümdür:
if [[ ${!BASH_VERSINFO[*]} == '' ]]; then
echo no-such
elif [[ ${!BASH_VERSINFO[*]} == '0' ]]; then
echo not-array
elif [[ ${!BASH_VERSINFO[*]} != '0' ]];
echo is-array
fi
Geçmişte bu konuda bir varyasyon kullandım:
while read _line; do
if [[ $_line =~ ^"declare -a" ]]; then
...
fi
done < <( declare -p )
bu da bir alt kabuk gerekir.
Daha olası bir teknik daha compgen
:
compgen -A arrayvar
Bu, tüm dizinlenmiş dizileri listeler, ancak ilişkilendirilebilir diziler özel olarak ele alınmaz (bash-4.4'e kadar) ve normal değişkenler olarak görünür ( compgen -A variable
)