연도 월을 다른 형식으로 변환

연도 월을 다른 형식으로 변환

연도와 월 형식이 있는데 YYMM이를 형식으로 변환하고 싶습니다 YYYY Month. 연도는 항상 2000년 이후입니다. 예를 들면;

  • 1908된다2019 Aug
  • 1904된다2019 Apr
  • 2012된다2020 Dec
  • 2111된다2021 Nov

나는 아래와 같은 스크립트를 작성했습니다.

rand=(1908 1904 2012 2001 2111)
months=(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
for i in $rand
do
    echo ${i:2:2}
    if [ ${i:2:2} -lt 1 ] || [ ${i:2:2} -gt 12 ]
        then echo "Month: ${i:2:2}. Last 2 values must be a month between 01 and 12."
    fi

    printf "20${i:0:2} ${months[${i:2:2}]}"
done

하지만 몇 가지 오류가 발생합니다.

line 13: 08: value too great for base (error token is "08")

0이 채워진 한 자리 월은 어떤 곳에서는 문제가 되지만 다른 곳에서는 작동한다고 생각합니다.

Bash가 그것이 08단지 8. ${i:2:2}으로 변경해 보았습니다 $((i:2:2)). 그러나 그것은 작동하지 않습니다.

line 7: i:2:2: syntax error in expression (error token is ":2:2")

답변1

08잘못된 8진수로 해석됩니다. 0으로 시작하므로 8진수이고 를 포함하므로 유효하지 않습니다 8. 이는 산술적 맥락(정수 비교)에서 이 하위 문자열을 숫자로 사용하기 때문입니다. 숫자가 낮을 경우에는 동일한 문제가 발생 09하지만 07숫자가 낮을 경우에는 문제가 발생하지 않습니다.

다음 스크립트는 날짜 2000-01-01과 YY숫자 비트를 연도로 사용하여 계산을 수행합니다. 그런 다음 문자열의 나머지 부분을 월 수로 더하고 하루를 뺍니다. 이 계산은 YYMM코드가 참조 하는 달의 마지막 날에 이루어집니다 . 를 사용하면 %Y %b연도와 월이 YYYY Mon형식으로 출력됩니다.

#!/bin/bash

datecodes=(1908 1904 2012 2001 2111)

for datecode in "${datecodes[@]}"; do
        printf -v thedate '2000-01-01 +%s years +%s months -1 day' "${datecode:0:2}" "${datecode:2}"
        LC_ALL=C date -d "$thedate" +'%Y %b'
done

산출:

2019 Aug
2019 Apr
2020 Dec
2020 Jan
2021 Nov

GNU를 한 번만 호출하는 약간 더 효율적인 코드 date:

#!/bin/bash

datecodes=(1908 1904 2012 2001 2111)

for datecode in "${datecodes[@]}"; do
        printf '2000-01-01 +%s years +%s months -1 day\n' "${datecode:0:2}" "${datecode:2}"
done | LC_ALL=C date -f - +'%Y %b'

2013 Apr이 코드를 사용하면 다음 과 같은 코드를 작성할 수 있습니다 1040.

POSIX 로케일이 아닌 현재 로케일에 따라 형식화된 약식 월 이름을 얻으려면 LC_ALL=C에 대한 호출 앞에 제거하십시오 date.


GNU 없이 작업하고 date, 날짜 코드의 월 부분을 검증하면서 동일한 접근 방식을 사용합니다.

#!/bin/bash

datecodes=(1908 1904 2012 2001 2111 1040)

declare -A months
months=(
        [01]=Jan [02]=Feb [03]=Mar
        [04]=Apr [05]=May [06]=Jun
        [07]=Jul [08]=Aug [09]=Sep
        [10]=Oct [11]=Nov [12]=Dec
)

for datecode in "${datecodes[@]}"; do
        YY=${datecode:0:2}
        MM=${datecode:2}

        if [ -z "${months[$MM:-empty]}" ]; then
                printf '"%s" is an invalid month\n' "$MM" >&2
                continue
        fi

        printf '20%s %s\n' "$YY" "${months[$MM]}"
done

이는 months연관 배열로 사용됩니다.

답변2

아래 방법으로 수행 원하는 출력을 얻기 위해 언급된 입력에 날짜를 추가했습니다.

여기에 유효한 입력에 대한 구조에 언급된 입력에 날짜 "01"을 추가했습니다.

for i in 1908 1904 2012 2111; do date +%Y" "%b -d $i"01"; done

산출

2019 Aug
2019 Apr
2020 Dec
2021 Nov

관련 정보