Bashの連想配列から逆順にファイルを印刷する

Bashの連想配列から逆順にファイルを印刷する
for key in ${!current_file[@]} 
    do
      echo $key      
     done

bashでcurrent_fileを次のように宣言します。

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

上記の最後の項目を除いて、ハッシュに少なくとも1つの要素が含まれているとします(引数がnullキーを持つ要素があるかのように出力されprintf '%s\0'ないため)。\0

とにかく引用符なしで書くことはほとんど意味がありません${!current_file[@]}。なぜなら、そのキーリストから分割+グローブ演算子を呼び出すからです。

答え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

関連情報