我有下面的脚本,我注意到这种情况下的 for 循环是按照我指定的顺序执行的,即。预计 2018,2019,2020,但结果为 2019,2018,2020。
在 shell 脚本中是否有特定的原因,是否有任何方法可以保留顺序。
#!/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