Skip to content

Perl 循环

while 循环

基本 while 循环

perl
my $count = 0;

while ($count < 5) {
    print "Count: $count\n";
    $count++;
}

使用 while 读取文件

perl
open(my $fh, '<', 'file.txt') or die "Cannot open file: $!";

while (my $line = <$fh>) {
    chomp $line;
    print "$line\n";
}

close($fh);

无限循环

perl
my $count = 0;

while (1) {
    print "Count: $count\n";
    $count++;
    last if $count >= 5;  # 使用 last 退出
}

until 循环

untilwhile not 的简写,当条件为假时继续循环。

基本 until 循环

perl
my $count = 0;

until ($count >= 5) {
    print "Count: $count\n";
    $count++;
}

使用 until 等待条件

perl
my $ready = 0;

until ($ready) {
    print "Not ready yet, waiting...\n";
    sleep 1;
    $ready = 1;  # 模拟条件变为真
}

print "Ready!\n";

for 循环

基本 for 循环

perl
for (my $i = 0; $i < 5; $i++) {
    print "i = $i\n";
}

C 风格的 for 循环

perl
for (my $i = 10; $i > 0; $i--) {
    print "Countdown: $i\n";
}

多个初始化和迭代

perl
for (my $i = 0, my $j = 10; $i < 10 && $j > 0; $i++, $j--) {
    print "i=$i, j=$j\n";
}

省略部分

perl
# 省略初始化
my $i = 0;
for (; $i < 5; $i++) {
    print "i = $i\n";
}

# 省略条件(无限循环)
for (my $i = 0; ; $i++) {
    print "i = $i\n";
    last if $i >= 5;
}

# 省略迭代
for (my $i = 0; $i < 5;) {
    print "i = $i\n";
    $i++;
}

foreach 循环

基本 foreach 循环

perl
my @fruits = ("apple", "banana", "orange");

foreach my $fruit (@fruits) {
    print "Fruit: $fruit\n";
}

简化写法(使用 $_)

perl
my @numbers = (1, 2, 3, 4, 5);

foreach (@numbers) {
    print "Number: $_\n";
}

修改数组元素

perl
my @numbers = (1, 2, 3, 4, 5);

foreach my $num (@numbers) {
    $num *= 2;  # 修改会反映到数组中
}

print "@numbers\n";  # 2 4 6 8 10

遍历哈希

perl
my %person = (name => "Alice", age => 25, city => "New York");

# 遍历键
foreach my $key (keys %person) {
    print "$key: $person{$key}\n";
}

# 遍历键值对
while (my ($key, $value) = each %person) {
    print "$key: $value\n";
}

循环控制

last - 退出循环

perl
for (my $i = 0; $i < 10; $i++) {
    print "i = $i\n";
    last if $i == 5;  # 退出循环
}

next - 跳过本次迭代

perl
for (my $i = 0; $i < 10; $i++) {
    next if $i % 2 == 0;  # 跳过偶数
    print "Odd number: $i\n";
}

redo - 重新开始当前迭代

perl
for (my $i = 0; $i < 5; $i++) {
    print "Start of iteration $i\n";
    
    if ($i == 2) {
        $i--;  # 递减以便重新开始
        redo;
    }
    
    print "End of iteration $i\n";
}

标签和嵌套循环

perl
OUTER: for (my $i = 0; $i < 5; $i++) {
    INNER: for (my $j = 0; $j < 5; $j++) {
        print "i=$i, j=$j\n";
        last OUTER if $i == 2 && $j == 2;  # 退出外层循环
        last INNER if $j == 2;  # 退出内层循环
    }
}

do-while 和 do-until

do-while 循环

perl
my $count = 0;

do {
    print "Count: $count\n";
    $count++;
} while ($count < 5);

do-until 循环

perl
my $count = 0;

do {
    print "Count: $count\n";
    $count++;
} until ($count >= 5);

确保至少执行一次

perl
my $number;

do {
    print "请输入正数: ";
    chomp($number = <STDIN>);
} while ($number <= 0);

print "你输入了: $number\n";

map 和 grep

map - 转换列表

perl
my @numbers = (1, 2, 3, 4, 5);

# 将每个元素乘以 2
my @doubled = map { $_ * 2 } @numbers;
print "@doubled\n";  # 2 4 6 8 10

# 转换为大写
my @words = qw(hello world perl);
my @upper = map { uc } @words;
print "@upper\n";  # HELLO WORLD PERL

# 创建键值对
my @fruits = qw(apple banana orange);
my %prices = map { $_ => rand(10) } @fruits;

grep - 过滤列表

perl
my @numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

# 获取偶数
my @evens = grep { $_ % 2 == 0 } @numbers;
print "@evens\n";  # 2 4 6 8 10

# 获取大于 5 的数
my @greater_than_five = grep { $_ > 5 } @numbers;
print "@greater_than_five\n";  # 6 7 8 9 10

# 使用正则表达式过滤
my @words = qw(apple banana orange grape);
my @with_a = grep { /a/ } @words;
print "@with_a\n";  # apple banana orange grape

map 和 grep 组合

perl
# 先过滤再转换
my @numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
my @evens_doubled = map { $_ * 2 } grep { $_ % 2 == 0 } @numbers;
print "@evens_doubled\n";  # 4 8 12 16 20

# 先转换再过滤
my @squared_even = grep { $_ % 2 == 0 } map { $_ ** 2 } (1..10);
print "@squared_even\n";  # 4 16 36 64 100

循环标量

读取多行输入

perl
print "请输入文本(Ctrl+D 结束):\n";

while (my $line = <STDIN>) {
    chomp $line;
    print "你输入了: $line\n";
}

使用 <> 读取文件

perl
# 从命令行参数读取文件
while (my $line = <>) {
    chomp $line;
    print "$line\n";
}

读取文件到数组

perl
open(my $fh, '<', 'file.txt') or die "Cannot open file: $!";

# 读取所有行到数组
my @lines = <$fh>;
close($fh);

# 处理每一行
foreach my $line (@lines) {
    chomp $line;
    print "$line\n";
}

实践示例

示例 1:九九乘法表

perl
#!/usr/bin/perl
use strict;
use warnings;

for (my $i = 1; $i <= 9; $i++) {
    for (my $j = 1; $j <= $i; $j++) {
        printf "%dx%d=%-3d", $j, $i, $i * $j;
    }
    print "\n";
}

示例 2:查找质数

perl
#!/usr/bin/perl
use strict;
use warnings;

print "请输入上限: ";
chomp(my $limit = <STDIN>);

print "质数: ";
for (my $n = 2; $n <= $limit; $n++) {
    my $is_prime = 1;
    
    for (my $i = 2; $i * $i <= $n; $i++) {
        if ($n % $i == 0) {
            $is_prime = 0;
            last;
        }
    }
    
    print "$n " if $is_prime;
}
print "\n";

示例 3:斐波那契数列

perl
#!/usr/bin/perl
use strict;
use warnings;

print "请输入项数: ";
chomp(my $n = <STDIN>);

my @fib = (0, 1);

for (my $i = 2; $i < $n; $i++) {
    $fib[$i] = $fib[$i-1] + $fib[$i-2];
}

print "斐波那契数列前 $n 项: @fib\n";

示例 4:文件处理

perl
#!/usr/bin/perl
use strict;
use warnings;

my $file = "data.txt";

open(my $fh, '<', $file) or die "Cannot open $file: $!";

my $line_count = 0;
my $word_count = 0;
my $char_count = 0;

while (my $line = <$fh>) {
    chomp $line;
    $line_count++;
    $char_count += length($line);
    
    my @words = split /\s+/, $line;
    $word_count += scalar @words;
}

close($fh);

print "统计结果:\n";
print "行数: $line_count\n";
print "单词数: $word_count\n";
print "字符数: $char_count\n";

示例 5:密码猜测

perl
#!/usr/bin/perl
use strict;
use warnings;

my $correct_password = "secret";
my $attempts = 0;
my $max_attempts = 3;

while ($attempts < $max_attempts) {
    print "请输入密码: ";
    chomp(my $password = <STDIN>);
    
    if ($password eq $correct_password) {
        print "密码正确!\n";
        last;
    } else {
        $attempts++;
        my $remaining = $max_attempts - $attempts;
        
        if ($remaining > 0) {
            print "密码错误,还有 $remaining 次尝试机会\n";
        } else {
            print "密码错误,尝试次数已用尽\n";
        }
    }
}

小结

本章节学习了 Perl 的循环:

  1. ✅ while 循环
  2. ✅ until 循环
  3. ✅ for 循环
  4. ✅ foreach 循环
  5. ✅ 循环控制(last、next、redo)
  6. ✅ do-while 和 do-until
  7. ✅ map 和 grep
  8. ✅ 文件读取循环

接下来,我们将学习 Perl 子程序(函数)