cshで日付チェックするシェルを作成

会社でちょっとしたツールをシェル(csh)で作ったりしています。その中で入力値(というよりも引数で与えられる値)の日付チェックを行っておいた方が良いなぁ、と思うことが度々あったので、簡単なシェルを書いてみました。usageの表示や閏年のチェック部分など、もう少しスマートに出来そうな部分もありますが、そこは後々修正することにします。(引数の桁数チェックにawkを使っているのがちょっとダサいですよね…。)同じことをやろうとしてる人の参考になれば幸いです。

誤りがあったので修正したしました。下記のリンク先の内容をご確認ください。

checkdate

#! /bin/csh -f

# 桁数チェック
# 8桁でない場合、usageを表示

echo $1 > input_value_$$.dat
if (`awk '{print length($1)}' input_value_$$.dat` != 8 ) then
  echo usage : $0 YYYYMMDD
  rm -f *_$$.dat
  exit 1
endif

# 値の妥当性チェック
# 入力値を分割して変数にセット
# 月、日については先頭の0を削除しておく

set YEAR = `cut -c1-4 input_value_$$.dat`
if (`cut -c5-5 input_value_$$.dat` == 0) then
  set MONTH = `cut -c6-6 input_value_$$.dat`
else
  set MONTH = `cut -c5-6 input_value_$$.dat`
endif
if (`cut -c7-7 input_value_$$.dat` == 0) then
  set DAY = `cut -c8-8 input_value_$$.dat`
else
  set DAY = `cut -c7-8 input_value_$$.dat`
endif

# 年のチェック ( 0000 - 9999 )

if ( ! `echo $YEAR | egrep '^[0-9]{4}$'` ) then
  echo "YEAR check error."
  rm -f *_$$.dat
  exit 1
endif

# 月のチェック ( 1 - 12 )

if ( ! `echo $MONTH | egrep '^[1-9]$|^1[0-2]$'` ) then
  echo "MONTH check error."
  rm -f *_$$.dat
  exit 1
endif

# 日のチェック ( 基本 : 1 - 31 )

if ( ! `echo $DAY | egrep '^[1-9]$|^[12][0-9]$|^3[01]$'` ) then
  echo "DAY check error."
  rm -f *_$$.dat
  exit 1
endif

# 日のチェック ( 詳細 : 月ごとの最終日と閏年の考慮 )

set ENDDAY = (31 28 31 30 31 30 31 31 30 31 30 31)
set LASTDAY = $ENDDAY[$MONTH]

if ($MONTH == 2 && $YEAR % 4 == 0 && $YEAR % 100 != 0) then
    @ LASTDAY += 1
else if ($MONTH == 2 && $YEAR % 400 == 0 ) then
    @ LASTDAY += 1
endif

if ( $DAY > $LASTDAY ) then
  echo "DAY check error."
  rm -f *_$$.dat
  exit 1
endif

echo OK

rm -f *_$$.dat

上記のサンプルではエラーがあった場合にechoで標準出力にメッセージを出していますが、実際にはechoを全て消して、別のシェルから呼び出して、戻り値が0(正常終了)か1(エラー終了)かをチェックすれば良いと思います。上記のソースをみて「おいおい、そこバグってるぜ。」とか「おいおい、そこはこうやった方がエレガントでしょう。」と思った方は是非とも教えてくださいませ。cshじゃなくてBourne Shellの方がカッコ良いかも、と思ってBourne Shellで書こうと試みて失敗したのは秘密です…。