|
|
|
Perl基礎講座(4) 繰り返し処理 -ループについて- 繰り返し処理、ループってなんでしょう? もうちょっと噛み砕いて説明します。 構造がこのようなデータ配列 @address を作成したとします。
1つの処理ルーチンをまず作って、それをループで繰り返せばよいわけです。 やろうと思えばループを使わなくても処理ができますが、このような「ブロック」にまとまられるものは 効率からいって、ループを使うのがよいでしょう。 さて、ちょっと話が横にそれますが、このデータは固定長でしょうか、可変長でしょうか。 固定長というのは「ある一定の長さ」をデータの項目ごとに決めておく方法です。 可変長というのは「長さは固定でなく」データを区切り文字で区切って 識別します。 固定長はデータベースを使っていて、きっちりと構築をしている方には御馴染ですね。 一般的なCGIでは可変長のデータ構造です。理由は簡単だから(笑) ということで、先ほどのデータベース配列 @addressは 各々のデータを区切り文字「,」 で区切ってあるということにします。 さて、では配列@addressを作りましょう。 @address = ( "1,なむこ,とうきょうとなんとか市", "2,こなみ,おおさかけん", "3,じゃれこ,さいたまけん" );この区切り文字ごとで、データをsplit(分割)するには..そう、split というコマンドを使います。 前編の基礎講座3で書いたように、配列は それぞれのindexで呼び出すことができました。 $address[0]とすると、配列の最初のデータでしたね? splitはこんな風に書きます。 ($id,$username,$address) = split(/,/,$address[0]);さあ、じゃあ表示させてみましょうか。 kiso4_1.plとして保存して、実行してみてください。 @address = ( "1,なむこ,とうきょうとなんとか市", "2,こなみ,おおさかけん", "3,じゃれこ,さいたまけん" ); ($id,$username,$address) = split(/,/,$address[0]); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; exit;実行結果 うまく表示されましたね? さて、では この処理を、配列全部に対してループで処理できるようにしてみましょう。 kiso_4_2.pl @address = ( "1,なむこ,とうきょうとなんとか市", "2,こなみ,おおさかけん", "3,じゃれこ,さいたまけん" ); foreach $i (@address) { ($id,$username,$address) = split(/,/,$i); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; } exit;さあ、実行結果はいかに? foreach というループ制御のブロックで、splitをして、printを繰り返しています。 これで、先頭から最後まで自動的にループしてくれるわけです。 Perlではループの処理に、4つのコマンドを持っています。 while until for foreach です。 whileは条件式が真(TRUE)であればループします。 while ($length < 1000) { loopさせたいコマンド; #ここで$lengthが条件式に合致しない値になることで $length の処理; #ループが終了する。 }$length よりも 1000が大きければ、ループが実行される、ということです。 untilは whileの逆、条件式が偽(FALSE)であればループします。 until ($length < 1000) { loopさせたいコマンド; $length の処理; #ここで$lengthが条件式に合致しない値になることで #ループが終了する。 }$length よりも 1000が大きくなかったらループが実行される、ということです。 forループ Cを使っていた人にはおなじみですね。 for (初期式; 条件式; 加減式) { loop中の命令; }と書きます。 実際にはこうなります。先ほどのforeach と同じように @addressを全部処理させるには for ($i=0; $i < @address; $i++) { ($id,$username,$address) = split(/,/,$address[$i]); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; }と、なります。 $i と @addressを比較しているので、ン!?と思う方もいらっしゃるかもしれません。 配列は、スカラーコンテキスト内で評価をすると、配列の要素数を返すんです。 気になる方は、この処理の前に要素数を入手してからやっても構いません。 $addcount = @address; #配列の要素数を変数addcountへ代入 for ($i=0; $i <= $addcount; $i++) { ($id,$username,$address) = split(/,/,$address[$i]); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; }foreachは、forと似ているものですが、配列の処理の時に便利です。 配列をループ時に自動的に変数へ展開してくれるので、 $address[$i]というような、配列のindexを指定してやらなくて済むのです。 foreach (@address) { } foreach $i (@address) { }の2つはほぼ、同じことをしています。 違いは変数の指定を明示的にしているか、いないかのみです。 foreach $i (@address) とすると、配列@addressの内容を$iにコピーをしながら、ループが実行されます。 明示的に変数を指定しなければ、特殊変数 $_ が使われます。 明示的な変数指定のforeach ループ foreach $i (@address) { ($id,$username,$address) = split(/,/,$i); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; }明示的な変数を指定しないforeach ループ foreach (@address) { ($id,$username,$address) = split(/,/,$_); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; }foreachには、一つ注意しておくことがあります。 要素を変数に展開していますが、この変数の内容を書き換えた場合 自動的に、その配列の内容も書き換わるのです。 覚えておきましょう。 さて、whileでも同じように、配列をそのままループすることができます。 ですが、foreachと同じように考えてはいけません。 配列 @addressの内容に全く手を触れなければ @addressはいつまでもデータがある状態=TRUEである。からです。 whileを使って配列を処理したい場合は、 @address = ( "1,なむこ,とうきょうとなんとか市", "2,こなみ,おおさかけん", "3,じゃれこ,さいたまけん" ); while (@address) { $i = shift(@address); #@addressの一番上のデータを変数$iに移す ($id,$username,$address) = split(/,/,$i); print "id NO: $id\n"; print "user : $username\n"; print "address: $address\n"; } exit;このようにするとうまくいきます。 shiftで値を削って、変数$iに移すことで、配列が空の状態を作りだすことができ、 データがなくなると同時に、ループが終了します。 なお、式条件が合致しなければ、一度もループが実行されないで次に処理が流れます。 while,until,for,foreachの処理中、ある条件に合致したら、即座にループを抜ける または、ある条件に合致したら、ループ制御内にあるコマンドを実行しないで、 再ループすることができます。 kiso4_3.plとして保存して、実行してみましょう。 $a=0; for(;;) { $a++; #インクリメント 1ずつ自動的に加算される if ($a == 10) { next; } #変数aが10になったら下に流れず再ループ elsif ($a == 15) { last; } #変数aが15になったらループを抜ける print "now loop count $a\n"; } ループの最初で $aに1ずつ加算して、if〜elsif、その後printしています。 まず、count 10が画面に表示されていませんね? 最初のif文では、$a == 10 となっています。 $aが10の時、nextという命令が実行されます。 ここで、下の命令へプログラムが流れることなく、次のループが実行されています。 次にelsif。$a == 15。 14まで表示されて、プログラムが終了していますね? 変数$aが15になったら、elsif文がtrueになるので、lastという命令が実行され、 ループが終了するのです。 ループ内の下の命令へ流れさせないで、次のループを開始させるのがnext ループ内の下の命令へ流れさせないで、即座にループを停止するのがlast です。おぼえておきましょう。 なお、先ほどのfor(;;) は無限ループの指示です。 ループ内に、きちんとした制御文(lastで抜ける)のを入れるのを忘れずに。 whileでの無限ループは 0が偽(FALSE)で、1以上なら真(TRUE) while(1) などと書くことで、whileで無限ループできます。 さて、では次は配列(2)の予定です。 |