
for key in ${!current_file[@]}
do
echo $key
done
Я объявляю current_file в bash следующим образом:
declare -A current_file
вставьте ключ как файл и размер как значение в current_file. Вывод цикла for выводит:
file2
file1
Я хочу напечатать как:
file1
file2
Как можно так печатать?
решение1
Чтобы вывести список ключей, отсортированных в алфавитном порядке, и предполагая, что это GNU sort
, вы можете сделать следующее:
printf '%s\0' "${!hash[@]}" | sort -z | tr '\0' '\n'
Или для перебора отсортированного списка ключей:
while IFS= read -rd '' -u3 key; do
something with "${hash[$key]}"
done 3< <(printf '%s\0' "${!hash[@]}" | sort -z)
Если вы можете гарантировать, что ключи не будут содержать символы новой строки, вы можете упростить это до:
printf '%s\n' "${!hash[@]}" | sort
С zsh
, это будет:
printf "%s\n" "${(ko@)hash}"
( k
чтобы получить ключи, o
чтобы упорядочить этот список, @
внутри двойных кавычек, чтобы сохранить пустой ключ, если таковой имеется (обратите внимание, что bash
в настоящее время существует ограничение, заключающееся в том, что он не может иметь элемент хеша с пустым ключом)).
И чтобы пройтись по ним циклом:
for key in "${(ko@)hash}"; do
something with "$hash[$key]"
done
Обратите внимание, что за исключением последнего пункта выше, мы предполагаем, что хеш содержит по крайней мере один элемент (поскольку printf '%s\0'
без аргумента вывод все равно будет таким \0
, как если бы был элемент с пустым ключом).
В любом случае, написание ${!current_file[@]}
без кавычек не имеет особого смысла, поскольку это вызовет оператор split+glob для этого списка ключей.
решение2
Ассоциативный массив в bash
похож на хеши/словари в типичных языках, и как и они он неупорядочен (на самом деле упорядочен в соответствии с внутренним значением хеша). Поэтому вы не можете ожидать, что вывод будет (в общем случае) отсортирован при итерации по (ассоциативным) ключам массива.
Вам необходимо отсортировать его самостоятельно, например, отправив STDOUT в STDIN sort
:
for key in ${!current_file[@]}; do
echo $key
done | sort
или что-то подобное.
Если вы хотите сохранить порядок, чтобы можно было выполнять любые операции на основе порядка с ключами/значениями ассоциативного массива, вы можете сохранить другой индексированный массив в качестве ссылки на вставку. Следующее должно дать вам базовую идею:
## Associative array `foo`
$ declare -A foo=([spam]=egg [baz]=cool)
## Reference indexed array `bar` containing the keys of `foo` sequentially indexed
$ bar=(spam baz)
## Retrieving in forward order
$ for i in "${bar[@]}"; do echo "$i :: ${foo[$i]}"; done
spam :: egg
baz :: cool
## Retrieving in reverse order
$ for ((i=${#bar[@]}-1; i>=0; i--)); do idx="${bar[$i]}"; echo "$idx :: ${foo[$idx]}"; done
baz :: cool
spam :: egg