Perl编程实践:基础与示例

table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}

1、编写并运行一个输出“Hello, world”的Perl程序。

实现 “Hello, world” 程序的方式

可使用以下几种方式实现 “Hello, world” 程序:

1. 编写文件

创建一个 Perl 文件,内容为:

perl
print "Hello, world!
";


保存后在命令行运行:

perl 文件名

若使用 v5.10 或更高版本,可写为:

perl
use v5.10;
say "Hello, world!";

2. 命令行运行

使用

-e

开关:

$ perl -e 'print "Hello, World
"'

使用

-l

开关自动添加换行符:

$ perl -le 'print "Hello, World"'

在 Windows 的

command.exe

(或

cmd.exe

)中,使用双引号在外:

C:> perl -le "print 'Hello, World'"

也可使用广义引号:

C:> perl -le "print q(Hello, World)"

v5.10 及更高版本使用

-E

开关启用新特性,可使用

say

2、编写一个程序,计算半径为 12.5 的圆的周长。圆的周长是 2π 乘以半径(约为 2 乘以 3.141592654)。你得到的答案应该约为 78.5。


#!/usr/bin/perl
use warnings;
$pi = 3.141592654;
$radius = 12.5;
$circ = 2 * $pi * $radius;
print "The circumference of a circle of radius $radius is $circ.
";

3、编写一个程序,提示用户输入一个圆的半径,然后根据输入的半径计算并输出该圆的周长。例如,如果用户输入的半径为 12.5,程序应计算并输出该半径对应的圆的周长。


#!/usr/bin/perl
use warnings;
$pi = 3.141592654;
print "What is the radius? ";
chomp($radius = <STDIN>);
$circ = 2 * $pi * $radius;
print "The circumference of a circle of radius $radius is $circ.
";

4、编写一个程序,提示用户输入两个数字(分别在不同的输入行),并输出这两个数字相乘的结果。

以下是实现该功能的程序:


print "Enter first number: ";
chomp($one = <STDIN>);
print "Enter second number: ";
chomp($two = <STDIN>);
$result = $one * $two;
print "The result is $result.
";

5、编写一个程序,提示用户输入一个字符串和一个数字(分别在不同的输入行),然后将该字符串按照数字指定的次数逐行输出。(提示:使用 x 运算符)。如果用户输入“fred”和“3”,输出应该是三行,每行都显示“fred”。如果用户输入“fred”和“299792”,可能会有大量输出。

以下是实现该功能的 Perl 代码示例:


print "请输入一个字符串: ";
my $string = <STDIN>;
chomp $string; # 去除换行符

print "请输入一个数字: ";
my $number = <STDIN>;
chomp $number; # 去除换行符

print ($string . "
") x $number;

这段代码首先提示用户输入一个字符串和一个数字,然后使用

x

运算符将字符串重复指定的次数,并逐行输出。

6、编写一个程序,逐行读取一系列数字,直到输入结束。然后,对于每个输入的数字,从以下列表中打印出对应的人名(将此人名列表硬编码到程序中,即该列表应出现在程序的源代码中)。例如,如果输入的数字是1、2、4和2,输出的人名将是fred、betty、dino和betty。人名列表为:fred betty barney dino wilma pebbles bamm – bamm

以下是一个用Python实现的示例代码:


names = ['fred', 'betty', 'barney', 'dino', 'wilma', 'pebbles', 'bamm - bamm']
while True:
    try:
        num = int(input())
        if 1 <= num <= len(names):
            print(names[num - 1])
        else:
            print('输入的数字超出范围')
    except EOFError:
        break

这段代码首先定义了人名列表,然后通过循环不断读取输入的数字,将数字转换为对应列表索引并打印出人名,直到遇到输入结束符。

7、编写一个名为 total 的子例程,它返回一个数字列表的总和。提示:该子例程不应执行任何输入/输出操作;它应仅处理其参数并将值返回给调用者。在这个示例程序中测试它,该程序只是测试子例程以查看其是否正常工作。第一组数字的总和应该是 25。代码如下:my @fred = qw{ 1 3 5 7 9 }; my $fred_total = total(@fred); print “The total of @fred is $fred_total.
”; print “Enter some numbers on separate lines: “; my $user_total = total(

); print “The total of those numbers is $user_total.
”; 注意,像这样在列表上下文中使用

将等待你以适合你系统的任何方式结束输入。

以下是实现该功能的代码:


sub total {
    my $sum = 0;
    foreach (@_) {
        $sum += $_;
    }
    return $sum;
}

该子例程使用

$sum

来保存总和,通过

foreach

循环遍历参数列表并累加每个参数,最后返回总和。为避免返回值可能为未定义,将

$sum

初始化为

0

8、编写一个名为 above_average 的子程序,它接受一个数字列表,并返回那些高于平均值(均值)的数字。(提示:编写另一个子程序,通过将总和除以项目数量来计算平均值。)在以下测试程序中测试你的子程序:my @fred = above_average(1..10); print “@fred is @fred
”; print “(Should be 6 7 8 9 10)
”; my @barney = above_average(100, 1..10);

以下是实现上述功能的代码:


sub total {
    my $sum = 0;
    foreach my $num (@_) {
        $sum += $num;
    }
    return $sum;
}

sub average {
    if (@_ == 0) { return }
    my $count = @_;
    my $sum = total(@_);
    return $sum/$count;
}

sub above_average {
    my $average = average(@_);
    my @list;
    foreach my $element (@_) {
        if ($element > $average) {
            push @list, $element;
        }
    }
    return @list;
}

my @fred = above_average(1..10);
print "@fred is @fred
";
print "(Should be 6 7 8 9 10)
";

my @barney = above_average(100, 1..10);
print "@barney is @barney
";

在上述代码中,

total

子程序用于计算数字列表的总和,

average

子程序用于计算平均值,

above_average

子程序用于返回高于平均值的数字列表。最后进行了测试调用。

9、编写一个名为 greet 的子程序,该子程序在欢迎你指定的人时,告知他们上一个被问候的人的名字。执行语句序列 greet( “Fred” ); greet( “Barney” ); 时,应输出:Hi Fred! You are the first one here! Hi Barney! Fred is also here!


use v5.10;

sub greet {
    state $last_person;
    my $name = shift;
    print "Hi $name! ";
    if ( defined $last_person ) {
        print "$last_person is also here!
";
    } else {
        print "You are the first one here!
";
    }
    $last_person = $name;
}

greet( 'Fred' );
greet( 'Barney' );

10、修改程序,使得当执行语句序列:greet( “Fred” ); greet( “Barney” ); greet( “Wilma” ); greet( “Betty” ); 时,能输出:Hi Fred! You are the first one here! Hi Barney! I’ve seen: Fred Hi Wilma! I’ve seen: Fred Barney Hi Betty! I’ve seen: Fred Barney Wilma 。

以下是修改后的程序:


use v5.10;

greet( 'Fred' );
greet( 'Barney' );
greet( 'Wilma' );
greet( 'Betty' );

sub greet {
    state @names;
    my $name = shift;
    print "Hi $name! ";
    if( @names ) {
        print "I've seen: @names";
    } else {
        print "You are the first one here!";
    }
    push @names, $name;
}

11、编写一个程序,要求用户在不同行输入一系列字符串,将每个字符串右对齐打印在一个20字符宽的列中。为确保输出列位置正确,同时打印一行数字作为“标尺线”(仅用于调试)。要确保不会误使用19字符宽的列。例如,输入“hello”和“good – bye”,输出应类似这样:123456789012345678901234567890123456789012345678901234567890

hello

good – bye

以下是实现该功能的Perl程序:


print "Enter some lines, then press Ctrl - D:
"; # or Ctrl - Z
chomp(my @lines = <STDIN>);
print "1234567890" x 7, "12345
"; # ruler line to column 75
foreach (@lines) {
    printf "%20s
", $_;
}

该程序首先提示用户输入一些行,然后按Ctrl – D(或Ctrl – Z)结束输入。接着读取并去除每行输入末尾的换行符。之后打印标尺线,最后通过循环将每行字符串右对齐打印在20字符宽的列中。

12、修改之前的程序,让用户选择列宽,这样依次输入 30、hello、good – bye(分行输入)时,字符串会显示在第 30 列。额外加分项:当所选宽度较大时,让标尺行更长。

以下是实现该功能的代码:


print "What column width would you like? ";
chomp(my $width = <STDIN>);
print "Enter some lines, then press Ctrl - D:
"; # or Ctrl - Z
chomp(my @lines = <STDIN>);
print "1234567890" x (($width+9)/10), "
"; # ruler line as needed
foreach (@lines) {
    printf "%${width}s
", $_;
}

或者使用另一种方式:


foreach (@lines) {
    printf "%*s
", $width, $_;
}

13、编写一个程序,要求用户输入一个名字,并根据以下名字和姓氏的对应关系输出对应的姓氏:弗雷德对应弗林斯通,巴尼对应鲁布尔,威尔玛对应弗林斯通。

以下是一个满足需求的 Perl 程序示例:


use v5.10;

# 定义名字和姓氏的映射
my %name_map = ( 
    'fred'   => 'flintstone', 
    'barney' => 'rubble', 
    'wilma'  => 'flintstone'
);

# 提示用户输入名字
print "请输入一个名字: ";
chomp(my $given_name = <STDIN>);
$given_name = lc $given_name; # 转换为小写以匹配映射

# 检查输入的名字是否在映射中
if (exists $name_map{$given_name}) {
    print "对应的姓氏是: $name_map{$given_name}
";
} else {
    print "未找到对应的姓氏。
";
}

这个程序首先定义了一个哈希表

%name_map

来存储名字和姓氏的映射。然后提示用户输入一个名字,将输入转换为小写以匹配映射。最后,检查输入的名字是否在映射中,如果是,则输出对应的姓氏;否则,输出未找到对应的姓氏的提示。

14、编写一个程序,逐行读取一系列单词,直到输入结束,然后输出每个单词出现的次数。例如,如果输入的单词是 fred、barney、fred、dino、wilma、fred(每行一个单词),输出应显示 fred 出现了 3 次。额外加分项:按代码点顺序对输出的单词进行排序。

以下是实现该功能的 Perl 代码:


my(@words, %count, $word);
chomp(@words = <STDIN>);
foreach $word (@words) {
    $count{$word} += 1;
}
foreach $word (sort keys %count) {
    print "$word was seen $count{$word} times.
";
}


代码解释:


首先声明变量,使用

<STDIN>

读取所有输入行到

@words

数组并去除换行符。第一个

foreach

循环遍历所有单词,将每个单词作为键,其出现次数作为值存储在

%count

哈希表中。第二个

foreach

循环按代码点顺序遍历哈希表的键,并输出每个单词及其出现次数。

15、编写一个程序,打印输入中提及“fred”的每一行,对其他行不做处理。判断输入字符串为“Fred”、“frederick”或“Alfred”时是否匹配。创建一个包含几行提及“fred flintstone”及其朋友的小文本文件,然后将该文件作为此程序的输入。

要实现该程序,可以使用正则表达式匹配

fred

。示例代码如下:


while (<>) {
    if (/fred/) {
        print;
    }
}

此程序只会匹配精确的

fred

,输入

Fred


frederick


Alfred

时不匹配。可创建一个小文本文件,将其作为输入运行此程序。

16、修改一个程序,使其能匹配“Fred”。若输入字符串是“Fred”、“frederick”或“Alfred”,判断修改后的程序是否能匹配这些字符串,并在文本文件中添加包含这些名字的行。

可将程序中的模式改为

/[fF]red/

,也可以尝试

/(f|F)red/


/fred|Fred/

,但字符类更高效。修改后,“Fred”能匹配,“frederick”和“Alfred”也能匹配,因为当前没有限定只匹配完整单词,后续会介绍相关功能来解决这个问题。

17、编写一个程序,打印出任何同时提及“wilma”和“fred”的输入行。

可使用正则表达式和循环遍历输入行,若一行同时包含“wilma”和“fred”则打印该行。示例代码(Python):


while True:
    try:
        line = input()
        if 'wilma' in line.lower() and 'fred' in line.lower():
            print(line)
    except EOFError:
        break

18、编写一个程序,该程序会反复要求用户猜测一个1到100之间的秘密数字,直到用户猜对为止。程序应使用神奇公式 int(1 + rand 100) 随机选取这个数字。当用户猜错时,程序应回应“Too high”或“Too low”。如果用户输入“quit”或“exit”,或者输入空行,程序应退出。当然,如果用户猜对了,程序也应退出!

以下是实现该功能的Perl代码:


my $secret = int(1 + rand 100);
while (1) {
    print "Please enter a guess from 1 to 100: ";
    chomp(my $guess = <STDIN>);
    if ($guess =~ /quit|exit|As*z/i) {
        print "Sorry you gave up. The number was $secret.
";
        last;
    } elsif ($guess < $secret) {
        print "Too low. Try again!
";
    } elsif ($guess == $secret) {
        print "That was it!
";
        last;
    } else {
        print "Too high. Try again!
";
    }
}

19、修改一个程序,使其在运行过程中打印额外的调试信息,例如它选择的秘密数字。进行修改,以便可以关闭此功能,并且在关闭时程序不会发出警告。如果你使用的是 Perl 5.10 或更高版本,请使用 // 运算符。否则,请使用条件运算符。


下面是给定的【文本内容】:

使用 Perl 5.10 或更高版本:

```perl
use v5.10;
my $Debug = $ENV{DEBUG} // 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Debug;

不使用 Perl 5.10 或更高版本:


my $Debug = defined $ENV{DEBUG} ? $ENV{DEBUG} : 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Debug;


##20、编写一个程序,找出命令行中指定的最旧文件并报告其存在天数。如果文件列表为空(即命令行中未提及任何文件),程序会怎样处理?
程序会直接报错,输出 `'No file names supplied!'` 并终止运行,因为没有文件可供检查,也就不存在最旧的文件。

##21、编写一个程序,使用堆叠文件测试运算符列出命令行中指定的所有可读、可写且归当前用户所有的文件。
以下是一个使用 Perl 语言实现的示例程序,该程序使用堆叠文件测试运算符列出命令行中指定的所有可读、可写且归当前用户所有的文件:

```perl
#!/usr/bin/perl
use v5.10;

foreach my $filename (@ARGV) {
    if (-r -w -o $filename) {
        print "$filename 是可读、可写且归你所有的文件。
";
    }
}

将上述代码保存为一个

.pl

文件,例如

file_test.pl

,然后在命令行中运行该程序并传入文件名作为参数,程序将输出所有满足条件的文件。例如:


perl file_test.pl file1.txt file2.txt

22、编写一个程序,向用户询问一个目录名,然后切换到该目录。如果用户输入的行只有空白字符,则默认切换到他或她的主目录。切换后,按字母顺序列出普通目录内容(不以点开头的项目)。如果目录切换不成功,只需提醒用户,但不要尝试显示内容。

以下是实现该功能的程序:


print "Which directory? (Default is your home directory) ";
chomp(my $dir = <STDIN>);
if ($dir =~ /As*z/) { # A blank line
    chdir or die "Can't chdir to your home directory: $!";
} else {
    chdir $dir or die "Can't chdir to '$dir': $!";
}
my @files = <*>;
foreach (sort @files) {
    print "$_
";
}

该程序首先提示用户输入目录名并去除换行符。若输入为空,则切换到主目录;否则,切换到用户指定的目录。切换成功后,使用通配符

<*>

获取目录中的普通文件和文件夹(不包含以点开头的隐藏文件),并按字母顺序排序后逐个打印。若切换目录失败,程序会输出错误信息并终止。

23、编写一个程序,其功能类似于

rm

命令,删除命令行中指定的所有文件。(你不需要处理

rm

命令的任何选项。)

在 Perl 中,可以使用

unlink

操作符来实现该功能。示例代码如下:


unlink @ARGV;
my $successful = unlink @ARGV;
print "I deleted $successful file(s) just now
";

上述代码中,

@ARGV

数组包含了命令行上提供的所有参数,也就是要删除的文件名列表。使用

unlink

操作符删除这些文件,并通过

$successful

变量来检查成功删除的文件数量。

如果需要详细了解每个文件的删除情况,可以按如下方式逐个删除文件:


foreach my $file (@ARGV) {
    unlink $file or warn "failed on $file: $!
";
}
© 版权声明

相关文章

暂无评论

none
暂无评论...