是否有一个bash命令可以告诉shell变量的大小

时间:2011-02-14 01:37:47

标签: linux bash

有没有办法从命令行中找到shell变量的大小(使用的内存),而不使用C?

4 个答案:

答案 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
}
相关问题