有没有办法从命令行中找到shell变量的大小(使用的内存),而不使用C?
答案 0 :(得分:18)
这可以告诉您名为“var”的标量变量的值中有多少个字符:
echo ${#var}
这告诉你名为“array”的数组中元素的数量:
echo ${#array[@]}
这将告诉您数组元素中的字符数:
echo ${#array[3]}
如果您尝试获取数组的大小并省略[@]
索引,则获得元素0的长度:
$ array=(1 22 333 4444)
$ echo ${#array}
1
$ echo ${#array[@]}
4
$ echo ${#array[2]}
3
如果你想要一个数组的所有元素的总长度,你可以迭代数组并添加它们,你可以使用IFS
和一些类似于下面的步骤,或者你可以:
$ tmp="${array[*]}"
$ echo $(( ${#tmp} - ${#array[@]} + 1 ))
10
谨防使用数组中的元素数作为最后一个元素的索引,因为Bash支持稀疏数组:
$ array=(1 22 333 4444 55555)
$ echo ${#array[@]}
5
$ array[9]=999999999
$ echo ${#array[@]}
6
$ echo ${array[${#array[@]} - 1]} # same as echo ${array[6 - 1]}
$ # only a newline is echoed since element 5 is empty (only if "nounset" option* is not set (default in most cases))
$ # when "nounset" option is set (possibly using command "set -u") then bash will print such error:
$ # bash: array[${#array[@]} - 1]: unbound variable
$ unset "array[1]" # always quote array elements when you unset them
$ echo ${#array[@]}
5
$ echo ${array[${#array[@]} - 1]} # same as echo ${array[5 - 1]}
55555
这显然不是最后一个因素。要获得最后一个元素:
$ echo ${array[@]: -1} # note the space before the minus sign
999999999
请注意,在即将发布的Bash 4.2中,您可以echo ${array[-1]}
获取最后一个元素。在4.2之前的版本中,负下标会出现错误的下标错误。
获取最后一个元素的索引:
$ idx=(${!array[@]})
$ echo ${idx[@]: -1}
9
然后你可以这样做:
$ last=${idx[@]: -1}
$ echo ${array[last]}
999999999
迭代稀疏数组:
for idx in ${!array[@]}
do
something_with ${array[idx]}
done
*我建议避免nounset
答案 1 :(得分:14)
wc
可以告诉你变量中有多少个字符和字节,而bash本身可以告诉你数组中有多少个元素。如果您正在寻找的是bash的内部结构对于保存特定变量的大小,那么我不相信它可以在任何地方使用。
$ foo=42
$ bar=(1 2 3 4)
$ echo -n "$foo" | wc -c -m
2 2
$ echo "${#bar[@]}"
4
答案 2 :(得分:1)
${#VAR}
告诉你字符串VAR
答案 3 :(得分:1)
对于标量变量,${#VAR}
为您提供字符长度。在unibyte语言环境中,这是以字节为单位的长度。以字节为单位的大小是以字节为单位的名称长度,加上以字节为单位的值的长度加上常量开销。
LC_ALL=C
name=VAR
size=$(($#name + $#VAR)) # plus a small overhead
如果导出变量,则大小约为两倍。
LC_ALL=C
name=VAR
size=$((($#name + $#VAR) * 2)) # plus a small overhead
对于数组变量,您需要总结元素的长度(再次,以字节为单位),并为每个元素添加一个常量开销加上数组的常量开销。
LC_ALL=C
name=VAR
size=$(($#name)) # plus a small overhead
for key in "${!VAR[@]}"; do
size=$((size + ${#key} + ${#VAR[$key]})) # plus a small overhead
done
这是一个经过最低限度测试的函数,用于计算变量占用的近似大小。数组和导出被考虑在内,但不是特殊的只读变量,例如$RANDOM
。已经在bash 4.2上观察到了这些大小,不同的版本可能会有不同的开销。您可能需要根据系统类型和malloc
实施情况调整常量。
_sizeof_pointer=4
_sizeof_int=4
_malloc_granularity=16
_malloc_overhead=16
## Usage: compute_size VAR
## Print the amount of memory (in bytes) used by VAR.
## The extra bytes used by the memory allocator are not taken into account.
add_size () {
local IFS="+" this extra
set $(($1 + _malloc_overhead))
_size=$((_size + $1))
set $(($1 % _malloc_granularity))
[[ $1 -eq 0 ]] || _size=$((_size + _malloc_granularity - $1))
}
compute_size () {
local LC_ALL=C _size=0 _key
if eval "[ -z \${$1+1} ]"; then echo 0; return; fi
add_size $((_sizeof_pointer*5 + _sizeof_int*2)) # constant overhead
add_size ${#1} # the name
case $(declare -p $1) in
declare\ -x*)
eval "add_size \${#$1}" # the value
eval "add_size \$((\${#1} + \${#$1} + 2))" # the export string
;;
declare\ -a*)
eval 'for _key in "${!'$1'[@]}"; do
add_size $_key
add_size ${#'$1'[$_key]}
add_size $((_sizeof_pointer*4))
done'
add_size $((_sizeof_pointer*2 + _sizeof_int*2))
add_size $((_sizeof_pointer*4))
;;
*)
eval "add_size \${#$1}" # the value
;;
esac
echo $_size
}