Есть ли команда bash, которая может определить размер переменной оболочки
есть ли способ найти размер (используемая память) переменной оболочки из командной строки без использования C ?
4 ответов
wc
может сказать вам, сколько символов и байтов находятся в переменной, а сам bash может сказать вам, сколько элементов находится в массиве. Если вы ищете, насколько велики внутренние структуры bash для хранения определенной переменной, то я не верю, что это доступно где-либо.
$ foo=42
$ bar=(1 2 3 4)
$ echo -n "$foo" | wc -c -m
2 2
$ echo "${#bar[@]}"
4
это говорит вам, сколько символов в значении скалярной переменной с именем "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
для скалярной переменной,${#VAR}
дает вам длину в символах. В unibyte locale это длина в байтах. Размер в байтах-это длина имени в байтах плюс длина значения в байтах плюс постоянные накладные расходы.
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 $(( + _malloc_overhead))
_size=$((_size + ))
set $(( % _malloc_granularity))
[[ -eq 0 ]] || _size=$((_size + _malloc_granularity - ))
}
compute_size () {
local LC_ALL=C _size=0 _key
if eval "[ -z ${+1} ]"; then echo 0; return; fi
add_size $((_sizeof_pointer*5 + _sizeof_int*2)) # constant overhead
add_size ${#1} # the name
case $(declare -p ) in
declare\ -x*)
eval "add_size ${#}" # the value
eval "add_size $((${#1} + ${#} + 2))" # the export string
;;
declare\ -a*)
eval 'for _key in "${!''[@]}"; do
add_size $_key
add_size ${#''[$_key]}
add_size $((_sizeof_pointer*4))
done'
add_size $((_sizeof_pointer*2 + _sizeof_int*2))
add_size $((_sizeof_pointer*4))
;;
*)
eval "add_size ${#}" # the value
;;
esac
echo $_size
}