키-값 쌍이 있는 루프의 경우 키가 정렬 순서를 유지하지 않습니다.

키-값 쌍이 있는 루프의 경우 키가 정렬 순서를 유지하지 않습니다.

나는 다음 스크립트를 가지고 있으며 이 경우 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

키(연도)는 숫자이므로 이 경우 인덱스 배열을 사용하지 않을 이유가 없는 것 같습니다.


인용하다:

  1. 연관 배열의 순서를 유지하는 방법은 무엇입니까?

답변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

관련 정보