我的格式中有年份和月份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")
我认为用零填充的个位数月份在某些地方是一个问题,但在其他地方却有效。
不知道如何让 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
.这样做是因为您将此子字符串用作算术上下文中的数字(整数比较)。您会遇到同样的问题,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
稍微高效的代码,只调用 GNUdate
一次:
#!/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'
请注意,此代码允许您将eg 编写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