[Perlトップページ]

繰り返し - while、for -

while文

while文は、C言語と同様に、条件式が満たされる間は実行文を繰り返します。下記の書き方に従います。

(正しい書き方)

while (条件式) {
    実行文;
}

実行文は複数行になっても構わないのですが、 注意してほしいのは実行文が1行でも

(誤った書き方)

while (条件式) 
    実行文;

としてはいけません。{ }で閉じなければいけません。 これは、他のif文、for文などでも同様です。

演習5-1

下記のスクリプトをkadai5-1.plとして書き、実行結果を確認せよ。

#!/usr/bin/perl

print "*** ケース1 ***\n";
$count = 1;
while ($count < 3) {
    print "\$count = $count\n";
    ++$count;
}
    
print "*** ケース2 ***\n";
$count = 1;
while ($count < 3) {
    print "\$count = $count\n";
    $count++;
}
(実行結果)

*** ケース1 ***
$count = 1
$count = 2
*** ケース2 ***
$count = 1
$count = 2

条件式は、式で表現されているとは限りません。下記の演習5-2では、 単に変数$countが( )の中に書いてあるだけです。 この場合には、「( )の中が正」というのが 条件式となります。つまり、 「( )の中が正である間は、 実行式を繰り返す」ということになります。

演習5-2

下記のスクリプトをkadai5-2.plとして書き、 4つのケースにおける実行結果の違いを確認せよ。

#!/usr/bin/perl

print "*** ケース1 ***\n";
$count = 1;
while ($count) {
    print "\$count = $count\n";
    --$count;
}

print "*** ケース2 ***\n";
$count = 1;
while ($count) {
    print "\$count = $count\n";
    $count--;
}

print "*** ケース3 ***\n";
$count = 1;
while (--$count) {
    print "\$count = $count\n";
}

print "*** ケース4 ***\n";
$count = 1;
while ($count--) {
    print "\$count = $count\n";
}
(実行結果)

*** ケース1 ***
$count = 1
*** ケース2 ***
$count = 1
*** ケース3 ***
*** ケース4 ***
$count = 0

while文は、ファイルを開き、その内容を読み込む際によく使用されます。 詳細は、ファイル入出力のページに 記述されていますが、ここでは簡単に紹介します。まず、 1995年から2001年までのデータが入っているテキストファイル kadai5-3.txtを作成してください。

kadai5-3.txt

1995 100
1996 110
1997 120
1998 130
1999 140
2000 150
2001 160

ここで、このkadai5-3.txtからデータを読み込み表示させたいとします。 これをPerlで記述するとすると、 「データを1行単位で読み込み、データのある行が存在する間は while文で繰り返す」という枠組みになります。 下記の例を見てください。

#!/usr/bin/perl

open (FILE, 'kadai5-3.txt') or die "$!";
while (<FILE>) {
    print $_;
}
close (FILE);
(実行結果)

1995 100
1996 110
1997 120
1998 130
1999 140
2000 150
2001 160

上記のスクリプトでは、<FILE>1行読み込む という命令を表しています。読み込んだ結果、ファイルの終わり ではなかったらwhile文の中を実行します。 読み込まれた1行分のデータは、文字列として $_ という デフォルト変数に入れられます。 それをprint文で表示させているわけです。

演習5-3

上記の例1のスクリプトをkadai5-3.plとして書き、実行結果を確認せよ。


ファイルからデータを読み込んで処理する際に、 「この場合になったら処理を終わらせたい」とか「この場合は 処理をしないでとばしたい」などの要求があると思います。 「この場合には」という表現は、 条件判断 - ifハ[ -で学習したif文を使いますが、 処理のループを抜け出したり、スキップしたりするのに lastnextを使います。 まず、lastを使った例を見てみましょう。

例:lastを用いた繰り返し

#!/usr/bin/perl

open (FILE, 'kadai5-3.txt') or die "$!";
while (<FILE>) {
    chomp $_;
    @data = split(/ /, $_);
    last if ($data[0] == 2000);
    print $_, "\n";
}

(または)

#!/usr/bin/perl

open (FILE, 'kadai5-3.txt') or die "$!";
while (<FILE>) {
    chomp $_;
    @data = split(/ /, $_);
    if ($data[0] == 2000){
        last;
    }
    print $_, "\n";
}

上記のスクリプトでの処理の流れは下記のとおりです。

  1. 読み込んできた1行単位の文字列に対し、chomp改行(\n)を取り除きます
  2. splitを用いて、空白単位で分割し、こまぎれになった文字列を @dataという配列に入れます。
  3. if文で配列@dataの1番目の要素$data[0]を対象にして、 「2000に等しければif文の中を実行せよ」と命令します。 もし$data[0]が2000に等しければ、つまりif文の条件式が真なら、 lastが実行され、ループを抜け出します。
  4. if文が真であれば、ループを抜け出しているのでprint文は実行されません。 if文が真でなければ、lastは実行されずループを抜け出さないので、 print文が実行されます。
  5. lastが実行されるとループも終了されるので、print文も実行されません。

次に、nextを使った例です。

例:nextを用いた繰り返し

#!/usr/bin/perl

open (FILE, 'kadai5-3.txt') or die "$!";
while (<FILE>) {
    chomp $_;
    @data = split(/ /, $_);
    next if ($data[0] == 2000);
    print $_, "\n";
}

(または)

#!/usr/bin/perl

open (FILE, 'kadai5-3.txt') or die "$!";
while (<FILE>) {
    chomp $_;
    @data = split(/ /, $_);
    if ($data[0] == 2000){
        next;
    }
    print $_, "\n";
}

上記の例3は基本的にほぼ例2と同じですが、違うのは 下記の点です。

  1. if文で配列@dataの1番目の要素$data[0]を対象にして、 「2000に等しければif文の中を実行せよ」と命令します。 もし$data[0]が2000に等しければ、つまりif文の条件式が真なら、 nextが実行され、繰り返しを次に進めます
  2. if文が真であれば、次のステップ<FILE>に進んでいるので print文は実行されません。if文が真でなければ、nextは実行されないので、 print文が実行されます。
  3. nextが実行されてもループは終了されないので、if文が真にならない限り print文は実行されます。

演習5-4

上記の例2のスクリプトをkadai5-4.plとして書き、実行結果を確認せよ。

演習5-5

上記の例3のスクリプトをkadai5-5.plとして書き、実行結果を確認せよ。

for文

for文も、C言語と同様に、条件式が満たされる間は実行文を繰り返します。 下記の書き方に従います。

for (初期化; 条件式; 増減式) {
    実行文;
}

演習5-6

下記のスクリプトをkadai5-6.plとして書き、実行結果を確認せよ。

#!/usr/bin/perl

print "*** ケース1 ***\n";
for ($count = 1; $count < 3; ++$count) {
    print "\$count = $count\n";
}
    
print "*** ケース2 ***\n";
for ($count = 1; $count < 3; $count++) {
    print "\$count = $count\n";
}
(実行結果)

*** ケース1 ***
$count = 1
$count = 2
*** ケース2 ***
$count = 1
$count = 2

foreach文

Perlでは、配列を用いた繰り返しには、foreachという便利な方法も使えます。

foreach 変数 (リスト) {
    実行文;
}

(例)
@name = ('Kawai', 'Yamamoto', 'Takada');
foreach $person (@name){
    print "$person\n";
}

上記の例では、$personという変数に、配列@nameの中身であるリストから、 要素が一つ一つ渡されていきます。要素が渡されるごとに print文が実行されます。このforeachでは、変数を省略できて、

@name = ('Kawai', 'Yamamoto', 'Takada');
foreach (@name){
    print "$_\n";
}

とも書き直せます。リストから読み込んだ要素はデフォルト変数 $_に渡されるというわけです。

for文の「増減式」が1つずつ増加していく場合には、 下記のようにforeachで書くこともできます。

foreach $count (1 .. 5) {
    print "\$count = $count\n";
}

上記の (1 .. 5) は、 (1, 2, 3, 4, 5) というリストと同じですので、

for ($count = 1; $count < 5; $count++){
    print "\$count = $count\n";
}

と全く同じ結果になります。

演習5-7

配列とリストで学習したように、 sortを使うと並び替えができる。下記には、 sortとforeachを併用した処理を示している。下記のスクリプトを kadai5-7.plとして書き、実行結果を確認せよ。

#!/usr/bin/perl

@name = ('Shimoda', 'Kawai', 'Yamamoto', 'Takada');
foreach (sort(@name)) {
    print $_, "\n";
}
(実行結果)

Kawai
Shimoda
Takada
Yamamoto

演算子x

演算子xを用いると、文字列の繰り返しができます。下記の例を見て下さい。

print '*' x 20, "\n";
********************

'*'が20回出力されて、改行されています。これを使えば 次のようなことができます。関数lengthにより、 文字列の長さを得ることができます。

$str = 'Caution !';
print '*' x length($str), "\n";
print $str, "\n";
print '*' x length($str), "\n";
(実行結果)

*********
Caution !
*********

演習5-8

下記のスクリプトをkadai5-8.plとして書き、実行結果を確認せよ。

#!/usr/bin/perl

@sentence = (
    "注意 !",
    "来週のゼミは休みです。",
    "次回のゼミは追って連絡します。"
);

foreach $str (@sentence){
    print '+', '-' x length($str), '+', "\n";
    print '|', $str, '|', "\n";
    print '+', '-' x length($str), '+', "\n";
}
(実行結果)

+------+
|注意 !|
+------+
+----------------------+
|来週のゼミは休みです。|
+----------------------+
+------------------------------+
|次回のゼミは追って連絡します。|
+------------------------------+

[Perl講座] [須崎純一トップページ]
須崎純一 京都大学大学 工学研究科都市環境工学専攻 環境情報学講座