Perl初歩の初歩

プログラミング言語Perlの初心者のためのわかりやすい解説ブログ(を目指しています)

open 歴史を残さなければ

2009-09-07 11:41:13 | 命令を覚えよう

プログラムを実行した結果を記録したい場合があります。また、すでに記録しているデータをプログラムに読み込ませて実行したい場合もあります。

たとえば、アクセスカウンターでは、まず前回までのアクセス数を読み込んで、それに1を足してものを新しいアクセス数として記録しているわけです。

データを読み込んだり、記録したりするのに、Perlでは open という命令を使います。

open(DAT, "counter.txt");
$count = <DAT>;
close(DAT);

print $count;

上記のプログラムは、counter.txt というファイルの1行目のデータを読み込んで表示しています。

open(ファイルハンドル, ファイル名) という形式で、読み込むファイルを指定します。
close(ファイルハンドル) という形式で、ファイルの指定を解除します。

ファイルハンドルとは、ファイルそのものを記号化したもので、ざっくり言ってしまえばファイル専用の変数のことです。特殊な変数なので、先頭に $ はつけません。

ファイルハンドルは自分で自由に命名して構いませんが、慣例として英字の大文字を使用しています。
FH とか FILE とか IN とか OUT などが多く使われているようです。ここでは DAT と名付けました。

<DAT> は ファイルからデータを読み込むときに使います。
上の場合、counter.txt の 1行目を読み込んで $count に入れています。

1行とは、「前回読み込み終わった直後」から、「次の改行記号の直後」までです。
つまり改行記号が(あれば)含まれます。
もし次の改行記号が見つからなければ、ファイルの最後まで読み込みます。

上の場合なら、open で 開いたすぐあとに <DAT> を使っているので、ファイルの先頭から1行を読み込んで、$count に入れているわけです。

次のような使い方もできます。

open(DAT, "data.txt");
$line1 = <DAT>;
$line2 = <DAT>;
close(DAT);

上の場合、$line1 には1行目が、$line2 には2行目が入ります。

したがって、ファイルを1行ずつ処理したい場合には、while を使って次のようにします。

open(DAT, "data.txt");
while ($line = <DAT>) {
  print $line;
}
close(DAT);

$line = <DAT> で 1行ずつ読み込んで表示します。
もし、読み込むべきデータが無くなったら while を抜けます。

ファイルの全部をいっぺんに読み込みたい場合には、

open(DAT, "data.txt");
@allbody = <DAT>;
close(DAT);

とします。
これは、ファイルの全部を1行ずつに分割して、配列に入れます。

もし、配列ではなくひとつの文字列としたいなら、上記の後に

$all = join('', @allbody);

とすればいいでしょう。


while 終わるまで何度でも

2009-06-10 15:32:50 | 命令を覚えよう

while (ホワイル) は、「~の間ずっと」という意味の英語です。

$x = 0;
$goukei = 0;
while ($goukei < 100) {
  $x++;
  $goukei += $x;
}
print $x;

上の例では、$goukei が 100未満の間ずっと { } の間を繰り返します。

まず、$x と $goukei を ともに 0 にしておきます。
次に、while の後ろの ( ) の部分の条件があてはまるかどうかを調べます。

$goukei は 0 で 100未満ですので条件があてはまるので、{ } の中に入ります。
$x++; は $x に 1 を足すという式。$x = $x + 1; を簡略化したもの。
$goukei += $x; は $goukei に $x を足した数を $goukei に入れるという式。$goukei = $goukei + $x; を簡略化したものです。

{ } の中を1回実行すると、$x は 1 になり、$goukei も 1 になります。

ここで、最初の条件のところに戻って、$goukei < 100 があてはまるかどうかを調べます。

$goukei は 1 で 100未満ですので条件があてはまるので、{ } の中に入ります。
$x++; で $x に 1 を足して 2 になります。
$goukei += $x; で $goukei に 2 を足して 3 になります。

ここで、最初の条件に戻って…

と繰り返すことになります。
この場合は、1 + 2 + 3 + … と足していって、100以上になるのは何を足した直後かがわかります。ちなみに答えは 14 です。

最後に $goukei が 105 となって、100未満ではなくなったときに、{ } の部分を無視して、先に進めるようになるわけです。


※ 注意してください!
while は うまくやらないと、いつまで経っても終わらないプログラムになってしまうという危険性があります。
条件がずっとあてはまっている場合、プログラムが終了しなくなり、いわゆる暴走している状態になるのです。

筆者も何度かやらかしてしまいました。

自分のWindowsパソコンでPerlが暴走してしまった場合には、あわてずに キーボードの [Ctrl] と [Shift] を押しながら [Esc] を押して「タスクマネージャー」を起動して、プロセスの中にある「perl.exe」を選択して、「プロセスの終了」ボタンをクリックすればOKです。

レンタルサーバーなどでは暴走させてはいけませんが、万が一の場合に備えて、多くのサーバーでは「30秒以上実行し続けているプログラムは強制的に終了させる」というような措置がとられているようです。


print 人間へのメッセージ

2009-05-31 14:53:38 | 命令を覚えよう

Perlでは、print には主に2つの意味があります。
ひとつは画面に表示すること、もうひとつはファイルに書き込むことです。

print "画面に表示します";

open(DAT, ">>test.dat");
print DAT "ファイルに書き込みます";
close(DAT);

いずれの場合も考え方は一緒で、コンピュータの内部で行った結果を、人間が確認できるように、画面上もしくはファイル上へ出力するわけです。

画面に表示するほうの print は、表示したい内容を print の後ろに書きます。

$x = '桜';
$menu{'Aランチ'} = '野菜炒め定食';
print 1 + 2;
print "$xは春に花が咲きます";
print "今日の昼ご飯は$menu{'Aランチ'}です";
print '$xは変数です';
print $x . 'の花は淡いピンクです';

上の例では、「3」「桜は春に花が咲きます」「今日の昼ご飯は野菜炒め定食です」「$xは変数です」「桜の花は淡いピンクです」と表示されます。

print の後ろに計算式があれば、計算した結果を表示します。
" " で囲んだ場合は、変数があればその中身に置き換えて表示します。
' ' で囲んだ場合は、そのまま表示します。
 . で変数とほかの文字とをつなぐことができます。


print <<__HTML__;
<a href="http://www.goo.ne.jp/">goo</a><br>
gooのトップページはこちら<br>
__HTML__

上の例は、print <<__HTML__; の次の行から、 __HTML__ の手前までをそのまま表示します。(ヒアドキュメントという)
__HTML__の部分はアルファベットや数字で自由に変えられます。

print <<goo;
<a href="http://www.goo.ne.jp/">goo</a><br>
gooのトップページはこちら<br>
goo

極端な話、上のようにしても大丈夫です。
print <<goo; のあとに、単独で goo が出てくるところまでを表示してくれるわけです。
ただ、この極端な例ではさすがに紛らわしいので、普通は大文字のアルファベットを用いるのが慣例となっています。
EOF や EOS や _HTML_ などを使う人が多いようです。


ファイルに書き込むほうの print は、また別の機会で。


foreach コツコツとしらみつぶしに

2009-05-02 12:09:40 | 命令を覚えよう

foreach は 配列に入っているデータを順番に1個ずつ取り出したいときに使います。

@obento = ("ご飯", "タコさんウインナー", "お漬け物");
foreach my $ryouri (@obento) {
  print "$ryori\n";
}

まず、@obento の中に 「ご飯」と「タコさんウインナー」と「お漬け物」を入れます。
次に foreach (フォーイーチ) を使って、@obento の中から一品ずつ料理を取り出して、表示させています。

表示結果は、

ご飯
タコさんウインナー
お漬け物

となります。

foreach my $ryouri (@obento) の部分で、@obento から順番にひとつずつ取り出して、$ryori に入れています。

my は変数の前につけて、「この変数はここでしか使わない変数です」ということを主張しています。この場合は、「$ryori という変数は、このforeachの中だけでしか使わない変数」という意味で、もしここ以外の場所で $ryori を使っていた場合は、別の変数として扱われます。
考えだすと難しいので、foreach my $~~ (@~~) {  } をセットで覚えてしまいましょう。