年と月を別の形式に変換

年と月を別の形式に変換

年と月の形式がありますが、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")

ゼロで満たされた1桁の月は、ある場所では問題になりますが、別の場所では動作すると思います。

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 と桁数を年として使用して計算します。次に、残りの文字列を特定の月数に加算し、1日を減算します。この計算は、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これは連想配列として使用されます。

おすすめ記事