Вместо arr+=([key]=value)
вы можете написать arr[key]=value
. Кроме того, $(())
и префикс $
для переменных не являются необходимыми внутри list[…]
.
declare -A arr
for (( i=0; i<"${#list[*]}"; i+=2 )); do
arr["${list[i]}"]="${list[i+1]}"
done
В остальном сценарий выглядит нормально. Я думаю, что единственной верной альтернативой является создание командной строки и eval
/ declare
этой. Следующая команда предполагает, что в list
есть хотя бы одна пара ключ-значение:
declare -A "arr=($(printf '[%q]=%q ' "${list[@]}"))"
Эта команда declare
должна быть безопасной. Также не должно быть проблем с ARG_MAX
, так как используются только встроенные модули. Тем не менее, l oop кажется быстрее на одну величину, см. Следующий тест. Не стесняйтесь тестировать оба подхода самостоятельно, используя ваши фактические данные (это того стоит только при работе с очень длинными массивами).
randList() {
# tr is necessary since the empty string cannot be used as a key
mapfile -d '' -n "$1" list < <(tr -s \\0 < /dev/urandom)
}
testFor() { declare -A arr; for (( i=0; i<"${#list[*]}"; i+=2 )); do arr["${list[i]}"]="${list[i+1]}"; done; }
testDeclare() { declare -A "arr=($(printf '[%q]=%q ' "${list[@]}"))"; }
prettyTime() { { time "$@"; } 2>&1 | grep -Eom1 '[0-9.sm]+'; }
for size in {1,10,50}000; do
randList "$size"
echo "list size = $size"
printf %s "for loop "; prettyTime testFor
printf %s "declare command "; prettyTime testDeclare
done
На моем ноутбуке (bash 5.0.16, intel i5 M 520) я получил эти результаты:
list size = 1000
for loop 0m0.059s
declare command 0m0.320s
list size = 10000
for loop 0m0.435s
declare command 0m2.395s
list size = 50000
for loop 0m2.540s
declare command 0m12.276s