PaddieのCGIの部屋        Since 2000.04.28

ここではPaddieが作ったCGIスクリプトの紹介やCGI (Webサーバーの設定やPerl) について、わかる範囲で(笑)解説します。
〜Last Modified : 16 May.2000〜


 
Perlってどう書くの?(4)
ファイルの読み込みまではできるようになりました。
では書き込みはどうするのでしょうか?

書き込む時も読み込みと同じようにopen説明を使います。

書き込みには「上書きモード」と「追記モード」があります。
上書きモード」ではファイルを一旦空にして、新しく書き込んでいきます。
追記モード」ではファイルの内容はそのままに、続きに付け足していきます。

---------- 例 4 ここから ----------
#!/usr/bin/perl
require "./jcode.pl";
open (IN,"./textfile.txt");
open (OUT,">./output.txt");
while ($line = <IN>)
  {
  &jcode'convert(*line,jis);
  print $line;
  print OUT $line;
  }
close IN;
close OUT;
$now = `date`;
open (LOG,">>./log.txt");
print LOG "$now";
close LOG;
exit;
---------- 例 4 ここまで ----------

ここでは「OUT」に読み込んだ内容を書き込むという処理が追加されていますね。

そして、「LOG」というファイルハンドルで簡単なログを取っています。
$now = `date`;説明とありますが、これはシステムに「date」コマンドを送った結果を$nowという変数に代入しています。
ですから、「Mon May 1 13:22:15 JST 2000」というような形のものが代入されます。

そして、log.txtを追記モードで開いて書き込み、ファイルを閉じています。

$nowには勝手に改行文字が含まれていますのでそのまま書き込めば改行されたことになります。

おわかりの通り、上書きモードは「>」追記モードには「>>」がそれぞれファイル名(パス)の前に付けられています。

しかし、全てのプラットフォームで「date」コマンドが同じ結果を示してくれるとは限りません。

そんなときにはこういう風にする方法もあります。

---------- 例 5 ここから ----------
#!/usr/bin/perl
require "./jcode.pl";
open (IN,"./textfile.txt");
open (OUT,">./output.txt");
while ($line = <IN>)
  {
  &jcode'convert(*line,jis);
  print $line;
  print OUT $line;
  }
close IN;
close OUT;
@month = ("Jan","Feb","mar","Apr","May","Jun","Jul","Aug","Aep","Oct","Nov","Dec");
@weekdays = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
($sec,$min,$hou,$day,$mon,$yea,$wday) = (localtime(time))[0,1,2,3,4,5,6];
$mon = $month[$mon];
$wday = $weekdays[$wday];
$yea += 1900;
$now = sprintf "%3s %3s %.2d %.2d:%.2d:%.2d JST %4d\n" ,$wday,$mon,$day,$hou,$min,$sec,$yea;
open (LOG,">>./log.txt");
print LOG "$now";
close LOG;
exit;
---------- 例 5 ここまで ----------

かなり複雑になってきました。

先ほどの例4と違うところを見てみましょう。
始めから12行(close OUT;まで)は全く同じです。その次の行からは違う方法になっていますね。

さて、今度は「@month」「@weekdays」と言うのが出てきました。一体何でしょうか?

これは「配列」といいます。配列というのは変数の集合体のようなもので、同じ名前の変数に添字インデックス)を付けて複数の物として扱う物です。

全体を表す時には「@」を付けて(@monthのような形です)表し、その中の個々のものを示すには普通の変数と同じように「$」を付け、後ろに「[]」内にインデックス数字)を付けて($month[3]のような形です)表します。(インデックスには数字だけでなく「数値を値に持つ変数」を入れることもできます。)

ですから、ここでは「@month」と「@weekdays」にそれぞれ右辺に書かれた複数の値を代入しているわけです。
そして、このような形で代入すると、インデックス0から順に代入されるようになっています。

次のものはどうでしょうか?

($sec,$min,$hou,$day,$mon,$yea,$wday) = (localtime(time))[0,1,2,3,4,5,6];となっていますね。
ここで、ちょっと見て下さい。後半の部分「(localtime(time))[0,1,2,3,4,5,6]」というところです。

そう、「[」と「]」で囲まれたものがありますね?配列に関係あるのでしょうか?

実は「localtime(time)」というのはPerlの組み込み関数を二つ使っているもので、「time説明」関数が1970年1月1日00:00:00からの経過秒数を示し、「localtime()説明」関数はカッコ内に数字を与えるとそれを1970年1月1日00:00:00からの経過秒数として該当する日付時刻等(システムのローカル時間帯での9要素)を含む配列を生成するのです。

そして、[0,1,2...]というのはその配列のインデックスを列記することで元になる配列のサブセットを一時的に作成します。(スライスといいます)

つまり、ここでは現在時刻の9要素から先頭の7つをそれぞれ$sec,$min,$hou,$day,$mon,$yea,$wdayにいっぺんに代入しているわけです。

この方法で取り出すと月名($mon)と曜日名($wday)が数字で表されてしまいます。月名は1月を0、曜日名は日曜日を0で表していますから、先ほど設定した月名(@month)、曜日名(@weekdays)の配列にそのまま対応できます。

そこで次の$mon = $month[$mon]; $wday = $weekdays[$wday];の二行で配列変数から該当する月名と曜日名を選んで代入しています。
代入される側(左辺)と同じ物が代入する側(右辺)にありますが、代入する場合は先に右辺が評価されますので、このような表記が可能です。

年は4桁のものから1900を引いた値が出ますので、それを補正するのに1900を足しておきます。

$yea += 1900というのは「$yea = $yea + 1900」と同じ意味です。

さて、この例の最後の解説になりました。「sprintf説明」です。

これは文字列を決まった形(フォーマット)に整形するときに使うものです。よく似たものに「printf説明」というのがあり、「sprintf説明」との違いは標準出力に結果が出力されるというものです。
ここでは標準出力に結果が表示されなくてもかまわないので「sprintf説明」を使っています。

引用符の中を見て下さい。

%」なんとかというのが並んでいますね。これはフォーマット制御文字列といって、ここに引用符のあとに続く変数の値を出現順に整形して埋め込むのですが、「%」の後の数字とアルファベットによって、その整形のしかたが定義されます。

ここでは三種類のフォーマット制御があります。
%3s」「%.2d」「%4d」となっていますが、それぞれ「文字列で三文字」「二桁の整数で桁が不足する場合は先頭から0で埋める」「整数4桁」と言う意味です。

結果として、「Mon May 01 13:22:15 JST 2000\n」と言うような形式のものが得られます。



Perlってどう書くの?(3)
CGIの部屋へ戻る
Perlってどう書くの?(5)

 


Copyright 1999-2000 Paddie
私宛のメールは"paddie@paddie.com"まで。

// TOPページ  // 掲示板  // MEMOちゃ  // CGIの部屋 //