私は次のスクリプトを持っており、この場合、forループが私が指定した順序で実行されることがわかりました。 2018年、2019年、2020年になると予想されたが、結果は2019年、2018年、2020年になった。
シェルスクリプトにこれに特別な理由があり、順序を保存する方法はありますか?
#!/bin/sh
declare -A arr
arr=( ["2018"]=5%12 ["2019"]=1%12 ["2020"]=1%2 )
INPUT_MONTH=$2
INPUT_YEAR=$1
#For loop to iterate the year(key) value of array
for year in ${!arr[@]}; do
echo ${year} ${arr[${year}]}
MONTH_RANGE=${arr[${year}]}
if [ ${year} -ge ${INPUT_YEAR} ]; then
START_MONTH=$(echo "${MONTH_RANGE}" | cut -d'%' -f 1)
END_MONTH=$(echo "${MONTH_RANGE}" | cut -d'%' -f 2)
# input year is equal and input month is different from default start one.
if [ "${year}" == "${INPUT_YEAR}" ]; then
START_MONTH=$INPUT_MONTH
fi
for mon in $(seq $START_MONTH $END_MONTH); do
echo "Process year:month <=> ${year}:${mon}"
done;
else
continue;
fi
done;
出力:
2019 1%12
Process year:month <=> 2019:1
Process year:month <=> 2019:2
Process year:month <=> 2019:3
Process year:month <=> 2019:4
Process year:month <=> 2019:5
Process year:month <=> 2019:6
Process year:month <=> 2019:7
Process year:month <=> 2019:8
Process year:month <=> 2019:9
Process year:month <=> 2019:10
Process year:month <=> 2019:11
Process year:month <=> 2019:12
2018 5%12
Process year:month <=> 2018:4
Process year:month <=> 2018:5
Process year:month <=> 2018:6
Process year:month <=> 2018:7
Process year:month <=> 2018:8
Process year:month <=> 2018:9
Process year:month <=> 2018:10
Process year:month <=> 2018:11
Process year:month <=> 2018:12
2020 1%2
Process year:month <=> 2020:1
Process year:month <=> 2020:2
答え1
Bashでdeclare -A arr
以下を宣言してください。関連大量に。連想配列のキーはハッシュされ、巡回順序は${!arr[@]}
保証されません1。
$ declare -A arr
$ arr=( ["2018"]=5%12 ["2019"]=1%12 ["2020"]=1%2 )
$ for year in "${!arr[@]}"; do printf '%s: %s\n' "${year}" "${arr[${year}]}"; done
2019: 1%12
2018: 5%12
2020: 1%2
代わりdeclare -a arr
に索引配列は期待どおりに整列する必要があります。
$ declare -a arr
$ arr=( [2018]=5%12 [2019]=1%12 [2020]=1%2 )
$ for year in "${!arr[@]}"; do printf '%s: %s\n' "${year}" "${arr[${year}]}"; done
2018: 5%12
2019: 1%12
2020: 1%2
キー(年)は数字なので、この場合インデックス配列を使用しない理由がないようです。
引用:
答え2
この場合、キーは数字なので、Steeldriverのソリューションを使用できます。
一般的なアプローチは、キーシーケンスのための追加の配列を提供することです。
declare -a ordered_keys
ordered_keys=(2018 2019 2020)
# or dynamically
ordered_keys=($(for key in "${!arr[@]}"; do printf '%s\n' "$key"; done | sort))
その後、交換
for year in ${!arr[@]}; do
あなたはそうです
for key in "${ordered_keys[@]}"; do