As Michael VehrsMichael Vehrs said, bash's associative arrays do not preserve insertion ordering. This is a "feature" of associative arrays in general. The "magic" for this in bash happens in hashlib.c.
Bash does have indexed arrays, which you could use as an indicator for the insertion order:
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
Another option, depending on your data, is a single indexed array whose values are the original key and value combined in some way (here, using a space):
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
... but if space is a valid part of a key or a value, then pick something else that's unused, such as a pipe symbol for example:
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