web-dev-qa-db-ja.com

bashにマップを挿入して注文

Bashに(挿入によって)順序付けられたマップはありますか?

私はbashに 連想配列 データ構造があることを知っていますが、それを反復するとき、要素の順序は挿入によるものではありません。以下の例。

地図を挿入順に並べておきたいのですが。

挿入配列を保持しない連想配列:

declare -A REPLACE_MAP
REPLACE_MAP['b']='2'
REPLACE_MAP['a']='1'
for key in "${!REPLACE_MAP[@]}"; do
    echo "$key - ${REPLACE_MAP["$key"]}"
    value=${REPLACE_MAP["$key"]}
done

結果:

a - 1
b - 2

次の結果が得られるデータ構造が必要です。

b - 2
a - 1
3

Michael Vehrs が言ったように、bashの連想配列は挿入順序を保持しません。これは 一般に連想配列 の「機能」です。これに対するbashの「魔法」は hashlib.c で発生します。

Bashには インデックス付き配列 があります。これは、挿入順序のインジケーターとして使用できます。

declare -A REPLACE_MAP
declare -a REPLACE_MAP_INDEX
REPLACE_MAP['b']='2'
REPLACE_MAP_INDEX+=('b')
REPLACE_MAP['a']='1'
REPLACE_MAP_INDEX+=('a')
for key in "${REPLACE_MAP_INDEX[@]}"; do
    printf "%s - %s\n" "$key" "${REPLACE_MAP["$key"]}"
    value=${REPLACE_MAP["$key"]}
done

データに応じて、別のオプションは、値が何らかの方法(ここではスペースを使用)で結合された元のキーと値である単一のインデックス付き配列です。

unset arr
declare -a arr
arr+=("b 2")
arr+=("a 1")
for ckey in "${arr[@]}"; do
  key=${ckey% *}
  value=${ckey#* }
  printf "%s - %s\n" "$key" "$value"
done

...しかし、スペースがキーまたは値の有効な部分である場合は、たとえばパイプ記号など、未使用のものを選択します。

unset arr
declare -a arr
arr+=("b|2")
arr+=("a|1")
for ckey in "${arr[@]}"; do
  key=${ckey%|*}
  value=${ckey#*|}
  printf "%s - %s\n" "$key" "$value"
done
6
Jeff Schaller