カレンダープログラムは、いろんなふうに応用できますが、これをダイアリーを自動的に作成するプログラムに使ってみました。ダイアリーといっても、ウェブ・ダイアリーで、日付と曜日のならんだ HTML ファイルを作って、そこに日誌ふうの記事を書き、ウェブにアップロードするというものです。次がその全体です。
#!/usr/bin/perl
#
# diary.pl -- Web Diary Maker
#
@yobi = qw(日 月 火 水 木 金 土);
$input = @ARGV[0];
if($input eq ""){
print "Input year and month in 4 digits.\n";
print "Example: Input '0204' for April, 2002.\n";
exit(0);
}
# 年月は4桁で入力する(2002年4月は 0204 と入れる)
$c_month = $input % 100;
$c_year = ($input - $c_month) / 100;
$year = 2000 + $c_year;
$month = $c_month;
# 先月と次月を得る
$p_year = $c_year - ($c_month == 1);
$n_year = $c_year + ($c_month == 12);
$p_month = $c_month - ($c_month > 1) + 11 * ($c_month == 1);
$n_month = $c_month + ($c_month < 12) - 11 * ($c_month == 12);
# 年月が1桁の場合、先頭に 0 をつける
if ($c_year < 10){
$c_year = "0$c_year";
}
if ($p_year < 10){
$p_year = "0$p_year";
}
if ($n_year < 10){
$n_year = "0$n_year";
}
if ($c_month < 10){
$c_month = "0$c_month";
}
if ($p_month < 10){
$p_month = "0$p_month";
}
if ($n_month < 10){
$n_month = "0$n_month";
}
# 作成するファイル名を決め、それを書き込みファイルとして開く
$datafile = "diary$c_year$c_month.html";
open OUT, "> $datafile" or die $!;
# 作業バーを画面に表示する
print "Making <$datafile> ";
# HTML ファイルの先頭部分を記入する
&print_top();
# 日付を入れる
($first_day, $last_date) = &find_first_last($year, $month);
$date = 1;
while ($date <= $last_date) {
$day = ($first_day + $date -1) % 7;
print OUT "<p><b>$month月$date日($yobi[$day])</b></p>\n\n";
$date++;
print ".";
}
# HTML ファイルの終わりの部分を記入する
&print_end();
print " done\n";
close(OUT);
exit(0);
sub find_first_last(){
local($year, $month, @month_days, $days, $i, $first_day, $last_day);
($year, $month) = @_;
@month_days = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
# うるう年の計算
if(($year % 4) == 0 and ($year % 100) != 0 or ($year % 400) == 0) {
$month_days[2] = 29;
}
# 1月1日の曜日の計算
$days = $year + int(($year-1)/4) - int(($year-1)/100) + int(($year-1)/400);
$i = 0;
while($i < $month){
$days += $month_days[$i];
$i++;
}
# その月の1日の曜日と日数を返す
$first_day = $days % 7;
$last_date = $month_days[$month];
return ($first_day, $last_date);
}
sub print_top()
{
my $print_text = << "_END_";
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<title>My Diary</title>
</head>
<body>
<h1 align="center">My Diary $year年$month月</h1>
<p align="center"><a href="diary$p_year$p_month.html">先月</a> <a href="diary$n_year$n_month.html">次月</a></p>
_END_
print OUT $print_text;
}
sub print_end()
{
my $print_text = << "_END_";
<br><div align="center"><form><input type=\"button\" value="ホームページにもどる" onclick="location='../index.html'"></form></div>
</body>
</html>
_END_
print OUT $print_text;
}
ここでは、こまかい部分の説明は抜きにして、大事なところだけ解説します。ファイルを開く命令は open <ファイルハンドル>, <ファイル名> で表します。次の部分がそうです。
# 作成するファイル名を決め、それを書き込みファイルとして開く $datafile = "diary$c_year$c_month.html"; open OUT, "> $datafile" or die $!;ここではファイルハンドルは、output の意味で OUT としましたが、好みのもので良いのです。伝統的に、大文字で書くことになっています。ファイル名は $datafile なんですが、書き込みファイルとして開くため "> $datafile" としました。
ファイルを読み込みファイルで開く場合は
open INP, "read.file";追記ファイルとして開く場合は
open ADD, ">> added.file"とすれば良く、コマンドラインで使う > や >> と同様で、わかりやすいと思います。ただし、
open OUT, > "write.file";とすると間違いになります。> や >> はかならず "" の中に入っていなければなりません。
open OUT, "> $datafile" or die $!; の die $! はエラーメッセージを出して終了するという意味です。それにしても「死ね」(die) なんて命令は穏やかではありませんね。
ファイルへの書き込みは
print OUT "<p><b>$month月$date日($yobi[$day])</b></p>\n\n";というように print <ファイルハンドル> <文字列> で行います。open の時と違って、ファイルハンドルのあとに , が入らないことにご注意ください。
書き込みが終わったら、開いたファイルは閉じておくほうが安全でしょう。exit(0) でも、ファイルを閉じることができるのですが、念のため
close(OUT);としておくと良いでしょう。
まとまった文字列を一挙にファイルに書き込むには、その文字列を変数にいれて、print OUT $print_text; としてやれば、print OUT "....."; という式を何行にもわたって書く必要がなくなります。そのテクニックが print_top() と print_end() で使っている $print_text = << "_END_"; という式です。
sub print_top()
{
my $print_text = << "_END_";
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<title>My Diary</title>
</head>
<body>
<h1 align="center">My Diary $year年$month月</h1>
<p align="center"><a href="diary$p_year$p_month.html">先月</a> <a href="diary$n_year$n_month.html">次月</a></p>
_END_
print OUT $print_text;
}
これは _END_ という文字が出てくるまで、そのあとに書かれた文字列を改行も含めてそのままの形で $print_text という変数に格納するさせる式です。print で "" でくくった文字列をあつかう場合、 " などの記号を場合は、次のように \ を使う必要があります。
print "<h1 align=\"center\">My Diary $year年$month月</h1>";しかし、上記の方法を使えば、\ は必要ありません。HTML ソースからカットしてきたものをそのまま使えるので便利です。