+# guess-ad-year.pl - 和暦を引数に与えると西暦年を応えてくれる
+# ad は A.D. (Anno Domini = 西暦年) の略
+# guess-ad-year.pl 平成30年
+# guess-ad-year.pl 昭和54年
+binmode( STDOUT, ':encoding(utf8)' );
+binmode( STDERR, ':encoding(utf8)' );
+# keyを各年号, valueに開始年と短縮形を格納した
+# ハッシュリファレンス, というデータ構造を作る
+ '明治' => { start => 1867, shortening => 'M' },
+ '大正' => { start => 1911, shortening => 'T' },
+ '昭和' => { start => 1925, shortening => 'S' },
+ '平成' => { start => 1988, shortening => 'H' },
+ '令和' => { start => 2018, shortening => 'R' },
+# 全角数字から半角数字へ変換するためのハッシュを作る
+# 正規表現によるバリデーションでは ^ と $ ではなく \A と \z を使おう
+# https://blog.tokumaru.org/2014/03/z.html
+my $regex = qr/\A(?<era>\w{1,2}?)(?<year>\d+|元)年\z/;
+my $decoded_input = decode( 'utf8', $input );
+my $regex_error = "昭和54年 などの形で入力してください\n";
+unless ( $decoded_input =~ /$regex/ ) {
+# 名前付きキャプチャを普通のスカラー変数に移す
+# 元号が'M, T, S, H, R'の場合はそれぞれ修正する
+$era = from_short_to_era($era);
+# 年数に「元」、つまり元年が入力された場合には1に置き換える
+$year = from_gannen_to_one($year);
+# 全角数値が入力されている場合は半角に置き換える
+$year = to_quantify_year($year);
+print '西暦' . ( $year + $JAPANESE_ERA{$era}->{start} ) . '年', "\n";
+# 元号が'M, T, S, H, R'の場合はそれぞれ修正する
+ return $era if length($era) > 1;
+ for my $key ( keys %JAPANESE_ERA ) {
+ return $key if $era eq $JAPANESE_ERA{$key}->{shortening};
+ if ( exists $JAPANESE_ERA{$era} ){
+ print "対応している元号は明治, 大正, 昭和, 平成, 令和 のみです\n";
+# 年数に「元」、つまり元年が入力された場合には1に置き換える
+sub from_gannen_to_one {
+# 全角数値が入力されている場合は半角に置き換える
+ # 入力された文字を1文字ずつ分割して配列に入れる
+ my @number = split //, $year;
+ for my $num (@number) {
+# 全角半角対応表にkeyが存在すれば、valueの値(半角数字)を
+ if ( exists $NUMBER{$num} ) {
+ $return_year .= $NUMBER{$num};
+# keyが存在しない場合には、そのまま返り値に文字列連結する