Bash: есть ли встроенный способ получить максимальную длину ключей в ассоциативном массиве

Как в Bash, учитывая ассоциативный массив, найти длину самого длинного ключа?

Скажем, я объявляю myArray, как показано ниже:

$  declare -A myArray=([zero]=nothing [one]='just one' [multiple]='many many')
$  echo ${myArray[zero]}
nothing
$  echo ${myArray[one]}
just one
$  echo ${myArray[multiple]}
many many
$

Я могу получить его, используя приведенный ниже однострочник

$  vSpacePad=`for keys in "${!myArray[@]}"; do echo $keys; done | awk '{print length, $0}' | sort -nr | head -1 | awk '{print $1}'`;
$  echo $vSpacePad
8
$

Я ищу что-то более простое, как показано ниже, но, к сожалению, это просто дает количество элементов в массиве.

$  echo "${#myArray[@]}"
3
$  echo "${#myArray[*]}"
3

person vtbr    schedule 22.04.2021    source источник


Ответы (2)


Есть ли встроенный способ получить максимальную длину ключей в ассоциативном массиве

No.

как найти длину самого длинного ключа?

Перебирайте элементы массива, получайте длину элемента и сохраняйте наибольшее число.

Не используйте обратные кавычки `. Вместо этого используйте $(..).

Расширения переменных в кавычках - не делайте echo $keys, делайте echo "$keys". Предпочтение от printf до echo.

Если элементы массива не имеют символов новой строки и других подозрительных символов, вы можете:

printf "%s\n" "${myArray[@]}" | wc -L
person KamilCuk    schedule 22.04.2021
comment
Размер моего однострочника был значительно уменьшен благодаря вашей комбинации printf и wc. Я собираюсь использовать это. Правда, для ключей "${!myArray[@]}" придется это сделать. - person vtbr; 22.04.2021
comment
Длина в байтах длины в char? printf "A\342\226\200b\n" | LANG=C wc -L -> 2, но printf "A\342\226\200b\n" | LANG=en_US.utf8 wc -L -> 3!! См. Длина строки в bash - person F. Hauri; 22.04.2021
comment
Length in byte of length in char? Ну, это не только utf-8, wc также обрабатывает табы (printf "\t\n" | wc -L -> 8) и CR (printf "123\r123\n" | wc -L = 3) и тому подобное. - person KamilCuk; 22.04.2021

Вам нужно перебирать ключи, но вам не нужны никакие внешние инструменты:

max=-1
for key in "${!myArray[@]}"; do
  len=${#key}
  ((len > max)) && max=$len
done
echo $max    # => 8

Если вы хотите вывести элементы массива по одному на строку, вам не нужен цикл: printf — ваш друг:

printf '%s\n' "${!myArray[@]}"

printf повторяется до тех пор, пока не будут использованы все аргументы

person glenn jackman    schedule 22.04.2021
comment
Это все еще нуждается в цикле. Я хотел избежать цикла for. Спасибо за совет по поводу printf - person vtbr; 22.04.2021
comment
@vtbr Вы должны выбрать между вилкой или петлей! В зависимости от количества элементов в вашем массиве, с небольшим массивом, цикл работает быстрее, чем вилка!! (Примечание: maxlen=$(printf "%s\n" "${!array[@]}" | wc -L) подразумевает как минимум 2 форка! - person F. Hauri; 22.04.2021