将年月转换为不同格式

将年月转换为不同格式

我的格式中有年份和月份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

相关内容