Печать файлов в обратном порядке из ассоциативного массива в bash

Печать файлов в обратном порядке из ассоциативного массива в bash
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

Связанный контент