我有一个变量名循环,我需要检查变量的内容是否为数组:
for varname in AA BB CC; do
local val
if [ "$varname" is array ]; then # how can I perform this test?
echo do something with an array
else
echo do something with a "'normal'" variable
fi
done
我该怎么做?
为避免调用 grep,您可以使用:
if [[ "$(declare -p variable_name)" =~ "declare -a" ]]; then
echo array
else
echo no array
fi
根据this wiki page,您可以使用以下命令:
declare -p variable-name 2> /dev/null | grep -q '^declare \-a'
从 bash 4.3 开始,它不再那么容易了。
使用“declare -n”,您可以添加对另一个变量的引用,并且可以一遍又一遍地执行此操作。好像这还不够复杂,使用“declare -p”,您不会得到类型或原始变量。
例子:
$ declare -a test=( a b c d e)
$ declare -n mytest=test
$ declare -n newtest=mytest
$ declare -p newtest
declare -n newtest="mytest"
$ declare -p mytest
declare -n mytest="test"
因此,您必须遍历所有引用。在 bash-only 中,这看起来像这样:
vartype() {
local var=$( declare -p $1 )
local reg='^declare -n [^=]+=\"([^\"]+)\"$'
while [[ $var =~ $reg ]]; do
var=$( declare -p ${BASH_REMATCH[1]} )
done
case "${var#declare -}" in
a*)
echo "ARRAY"
;;
A*)
echo "HASH"
;;
i*)
echo "INT"
;;
x*)
echo "EXPORT"
;;
*)
echo "OTHER"
;;
esac
}
用上面的例子:
$ vartype newtest
ARRAY
要检查数组,您可以修改代码或将其与 grep 一起使用:
vartype $varname | grep -q "ARRAY"
我从上面鲁本的精彩回答开始。我实施了一些评论和一些我自己的改进,并得出了这个结论:
#!/bin/bash
array_test() {
# no argument passed
[[ $# -ne 1 ]] && echo 'Supply a variable name as an argument'>&2 && return 2
local var=$1
# use a variable to avoid having to escape spaces
local regex="^declare -[aA] ${var}(=|$)"
[[ $(declare -p "$var" 2> /dev/null) =~ $regex ]] && return 0
}
现在我可以这样做了:
foo=(lorem ipsum dolor)
bar="declare -a tricky"
declare -A baz
array_test foo && echo "it's an array"
array_test bar && echo "it's an array"
# properly detects empty arrays
array_test baz && echo "it's an array"
# won't throw errors on undeclared variables
array_test foobarbaz && echo "it's an array"
另一种方式:
例如,创建一个数组:
Variable=(The Quick Brown Fox...)
测试变量:
if [ "${#Variable[@]}" -gt "1" ] ;
then echo "Variable is an Array";
else echo "Variable is NOT an Array" ;
fi
is_array() {
local variable_name=$1
[[ "$(declare -p $variable_name)" =~ "declare -a" ]]
}
is_array BASH_VERSINFO && echo BASH_VERSINFO is an array
is_array() {
local variable_name=$1
[[ "$(declare -p $variable_name 2>/dev/null)" =~ "declare -a" ]]
}
我认为这样做,它检查数组索引不匹配“”或“0”
对于小型阵列和非阵列,它应该很便宜。
它通过测试数组索引中的任何非零字符来工作
is_array() {
eval [[ "\"\${!$1[*]}\"" =~ "[1-9]" ]]
}
an_array=(1 2 3)
wierd_array[4]=3
non_array="Joe"
unset non_exist
is_array an_array && echo pass || echo fail
is_array wierd_array && echo pass || echo fail
is_array non_array && echo fail || echo pass
is_array non_exist && echo fail || echo pass
输出应该是
pass
pass
pass
pass