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

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

연도와 월 형식이 있는데 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으로 채워진 한 자리 월은 어떤 곳에서는 문제가 되지만 다른 곳에서는 작동한다고 생각합니다.

08Bash가 이것이 단지 이라는 것을 이해하도록 하는 방법을 잘 모르겠습니다 . . 로 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.

YY다음 스크립트는 날짜 2000-01-01과 자릿수를 연도로 사용하여 계산합니다. 그런 다음 나머지 문자열을 특정 월 수에 더하고 하루를 뺍니다. 이 계산은 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이 코드를 사용하면 예를 들어 code 로 작성할 수 있습니다 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

관련 정보