연도와 월 형식이 있는데 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