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;
}

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

rm

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

rm

的任何选项)

可以使用Perl语言编写如下程序来实现该功能:


#!/usr/bin/perl

# 获取命令行参数中的文件名列表
my @files = @ARGV;

# 使用unlink操作符删除文件
unlink @files;

将上述代码保存为一个

.pl

文件,例如

rm_like.pl

,然后在命令行中运行该程序并指定要删除的文件,如

perl rm_like.pl file1.txt file2.txt

,即可删除指定的文件。

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

mv

命令,将第一个命令行参数指定的文件重命名为第二个命令行参数指定的名称。(不需要处理

mv

命令的任何选项或额外参数。)要考虑目标可能是一个目录的情况;如果是目录,则在新目录中使用原文件的基本名称。

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


use File::Basename;
use File::Spec;

my($source, $dest) = @ARGV;

if (-d $dest) {
    my $basename = basename $source;
    $dest = File::Spec->catfile($dest, $basename);
}

rename $source, $dest or die "Can't rename '$source' to '$dest': $!
";

27、如果你的操作系统支持,编写一个程序来查找当前目录中的任何符号链接,并打印出它们的值(就像使用

ls -l

命令那样:名称 -> 值)。


foreach ( glob( '.* *' ) ) {
    my $dest = readlink $_;
    print "$_ -> $dest
" if defined $dest;
}

28、编写一个程序,读取一个数字列表并对其进行数值排序,然后将排序后的列表以右对齐的列形式输出。用以下示例数据进行测试:17 1000 04 1.50 3.14159 –10 1.5 4 2001 90210 666

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


use strict;
use warnings;
# 读取输入的数字
my @numbers;
while (<>) {
    push @numbers, split;
}
# 定义数值排序子程序
sub by_number {
    $a <=> $b
}
# 对数字进行排序
my @sorted_numbers = sort by_number @numbers;
# 输出排序后的数字,右对齐
foreach my $number (@sorted_numbers) {
    printf "%20g
", $number;
}

将上述示例数据输入该程序,即可得到排序后右对齐输出的结果。

29、编写一个程序,将以下哈希表的数据按姓氏进行不区分大小写的字母顺序排序。当姓氏相同时,再按名字(同样不区分大小写)排序。输出的第一个名字应该是 Fred 的,最后一个应该是 Betty 的。所有姓氏相同的人应该分组在一起。不要修改数据。名字的大小写应与下面所示保持一致。哈希表数据为:my %last_name = qw{ fred flintstone Wilma Flintstone Barney Rubble betty rubble Bamm – Bamm Rubble PEBBLES FLINTSTONE };

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


my %last_name = qw{ fred flintstone Wilma Flintstone Barney Rubble betty rubble Bamm - Bamm Rubble PEBBLES FLINTSTONE };
my @sorted_names = sort { lc($last_name{$a}) cmp lc($last_name{$b}) or lc($a) cmp lc($b) } keys %last_name;
foreach my $name (@sorted_names) {
    print "$name $last_name{$name}
";
}

30、编写一个程序,在给定的字符串中查找给定子字符串的所有出现位置,并打印出子字符串所在的位置。例如,给定输入字符串“This is a test.”和子字符串“is”,程序应报告位置2和5。如果子字符串是“a”,则应报告8。如果子字符串是“t”,程序会报告哪些位置?

程序会报告位置0、10和13。

31、使用

given

和智能匹配,编写一个程序,报告你在命令行指定的数字的所有因数(除了1和该数字本身)。例如,对于数字99,你的程序应报告它能被3、9、11和33整除。如果该数字是质数(没有因数),则报告该数字是质数。如果命令行参数不是数字,报告错误且不尝试计算因数。尽管你可以使用

if

结构和普通匹配来完成此任务,但只能使用智能匹配。

以下是满足需求的Perl程序:


use 5.010;
say "Checking the number <$ARGV[0]>";
given( $ARGV[0] ) {
    when( ! /Ad+/ ) {
        say "Not a number!"
    }
    my @divisors = divisors( $_ );
    my @empty;
    when( @divisors ~~ @empty ) {
        say "Number is prime"
    }
    default {
        say "$_ is divisible by @divisors"
    }
}
sub divisors {
    my $number = shift;
    my @divisors = ();
    foreach my $divisor ( 2 .. $number/2 ) {
        push @divisors, $divisor unless $number % $divisor;
    }
    return @divisors;
}

32、编写一个 Perl 程序,接收一个数字作为命令行参数,程序需要报告该数字是奇数还是偶数,该数字是否为质数(除了 1 和它本身没有其他除数),以及它是否能被你喜欢的数字(假设为 42)整除。仅使用智能匹配。


use 5.010;

say "Checking the number <$ARGV[0]>";
my $favorite = 42;

given( $ARGV[0] ) {
    when( ! /Ad+/ ) {
        say "Not a number!"
    }
    my @divisors = divisors( $ARGV[0] );
    when( @divisors ~~ 2 ) {
        # 2 是 @divisors 中的元素
        say "$_ is even";
        continue;
    }
    when( !( @divisors ~~ 2 ) ) {
        # 2 不是 @divisors 中的元素
        say "$_ is odd";
        continue;
    }
    when( @divisors ~~ $favorite ) {
        say "$_ is divisible by my favorite number";
        continue;
    }
    when( $_ ~~ $favorite ) {
        say "$_ is my favorite number";
        continue;
    }
    my @empty;
    when( @divisors ~~ @empty ) {
        say "Number is prime"
    }
    default {
        say "$_ is divisible by @divisors"
    }
}

sub divisors {
    my $number = shift;
    my @divisors = ();
    foreach my $divisor ( 2 .. ($number/2 + 1) ) {
        push @divisors, $divisor unless $number % $divisor;
    }
    return @divisors;
}

33、编写一个程序,将当前工作目录更改为某个特定的(硬编码的)目录,例如系统的根目录,然后执行

ls -l

命令以获取该目录的长格式目录列表。(如果使用非 Unix 系统,请使用自己系统的命令来获取详细的目录列表)。

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


chdir '/' or die "Can't chdir to root directory: $!";
exec 'ls', '-l' or die "Can't exec ls: $!";

第一行将当前工作目录更改为根目录,第二行使用多参数的

exec

函数将结果发送到标准输出。

34、编写一个程序来解析日期命令的输出,以确定当前是星期几。如果是工作日,则输出“get to work”;否则,输出“go play”。日期命令的输出在周一以“Mon”开头。若使用的是非Unix系统且没有日期命令,可编写一个简单的伪程序,使其输出类似日期命令可能输出的字符串。也可使用如下两行程序:#!/usr/bin/perl print localtime( ). “
”;

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


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

# 获取日期命令的输出
my $date_output = `date`;

# 提取星期几信息
if ($date_output =~ /^(Mon|Tue|Wed|Thu|Fri)/) {
    print "get to work
";
} else {
    print "go play
";
}

如果是非Unix系统没有

date

命令,可使用提供的伪程序:


#!/usr/bin/perl
my $date_output = localtime( ) . "
";

if ($date_output =~ /^(Mon|Tue|Wed|Thu|Fri)/) {
    print "get to work
";
} else {
    print "go play
";
}

35、(仅适用于Unix系统)编写一个无限循环程序,该程序能捕获信号,并报告捕获到了哪个信号以及之前看到该信号的次数。如果捕获到INT信号则退出程序。可以使用命令行的kill命令发送信号,如:$ kill -USR1 12345 ;若不能使用命令行的kill命令,也可编写另一个程序向它发送信号,例如使用Perl单行命令:$ perl -e ‘kill HUP => 12345’。

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


use 5.010;

sub my_hup_handler {
    state $n;
    say 'Caught HUP: ', ++$n
}

sub my_usr1_handler {
    state $n;
    say 'Caught USR1: ', ++$n
}

sub my_usr2_handler {
    state $n;
    say 'Caught USR2: ', ++$n
}

sub my_int_handler {
    say 'Caught INT. Exiting.';
    exit
}

say "I am $$";

foreach my $signal ( qw(int hup usr1 usr2) ) {
    $SIG{ uc $signal } = "my_${signal}_handler";
}

while(1) {
    sleep 1;
}

运行该程序后,你可以使用以下命令发送信号:


$ kill -HUP <进程ID>
$ perl -e 'kill HUP => <进程ID>'
$ perl -e 'kill USR2 => <进程ID>'

程序会输出捕获信号的情况,当捕获到INT信号时程序会退出。

36、编写一个程序,生成当前目录中文件的访问时间和修改时间(以纪元时间表示)的报告。使用stat函数获取这些时间,并使用列表切片提取元素。将结果以三列的形式报告,格式如下示例:fred.txt 1294145029 1290880566 barney.txt 1294197219 1290810036 betty.txt 1287707076 1274433310

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


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

# 获取当前目录下的所有文件
opendir(my $dh, '.') or die "无法打开当前目录: $!";
my @files = readdir($dh);
closedir($dh);

# 遍历每个文件
foreach my $file (@files) {
    next if (-d $file); # 跳过目录

    my @stat_info = stat($file);
    my $atime = $stat_info[8]; # 访问时间
    my $mtime = $stat_info[9]; # 修改时间

    printf("%-20s %-15d %-15d
", $file, $atime, $mtime);
}

该代码首先打开当前目录,读取其中的所有文件,然后遍历每个文件,使用

stat

函数获取文件的状态信息,通过列表切片提取访问时间和修改时间,最后以三列的形式输出结果。

37、修改练习2的答案,使用YYYY – MM – DD格式报告时间。使用带有localtime和切片的map将纪元时间转换为所需的日期字符串。注意localtime文档中关于它返回的年份和月份值的说明。你的报告应如下所示:fred.txt 2011 – 10 – 15 2011 – 09 – 28 barney.txt 2011 – 10 – 13 2011 – 08 – 11 betty.txt 2011 – 10 – 15 2010 – 07 – 24


foreach my $file ( glob( '*' ) ) {
    my( $atime, $mtime ) = map {
        my( $year, $month, $day ) = (localtime($_))[5,4,3];
        $year += 1900;
        $month += 1;
        sprintf '%4d-%02d-%02d', $year, $month, $day;
    } (stat $file)[8,9];
    printf "%-20s %10s %10s
", $file, $atime, $mtime;
}

38、编写代码打印“Hello, world!”,可以使用不同方式(如使用

print


say

,从命令行运行等)

以下是几种不同方式的代码示例:

使用

print

perl
print "Hello, world!
";

使用

say

(Perl 5.10 或更高版本):

perl
use 5.010;
say "Hello, world!";

从命令行使用

-e

开关:

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

从命令行使用

-l

开关:

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

39、编写程序计算半径为12.5的圆的周长并输出

以下是使用Perl编写的程序来计算半径为12.5的圆的周长并输出:


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

my $radius = 12.5;
my $pi = 3.1415926;
my $circumference = 2 * $pi * $radius;

print "半径为12.5的圆的周长是:$circumference
";

将上述代码保存为一个

.pl

文件,例如

circle_circumference.pl

,然后在命令行中运行

perl circle_circumference.pl

即可看到结果。

40、编写程序让用户输入圆的半径,然后计算并输出该圆的周长

以下是使用Python语言实现的代码:


import math
radius = float(input("请输入圆的半径:"))
circumference = 2 * math.pi * radius
print("该圆的周长是:", circumference)

这段代码首先导入

math

模块以使用圆周率

pi

,然后通过

input

函数获取用户输入的半径并转换为浮点数,接着根据圆的周长公式计算周长,最后将结果输出。

41、编写一个Perl程序,计算半径为12.5的圆的周长并输出


#!/usr/bin/perl
use 5.014;
my $radius = 12.5;
my $circumference = 2 * 3.14159 * $radius;
say "半径为12.5的圆的周长是: $circumference";

42、编写一个Perl程序,提示用户输入圆的半径,然后计算并输出该圆的周长

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


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

print "请输入圆的半径: ";
my $radius = <STDIN>;
chomp($radius);

my $circumference = 2 * 3.14159 * $radius;
print "该圆的周长是: $circumference
";

将上述代码保存为一个

.pl

文件,例如

circle_circumference.pl

,然后在终端中运行

perl circle_circumference.pl

,按照提示输入圆的半径,程序将计算并输出圆的周长。

43、编写一个Perl程序,提示用户输入圆的半径,检查输入的半径是否为负数,如果是则将周长设为0,然后计算并输出该圆的周长

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


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

print "请输入圆的半径: ";
my $radius = <STDIN>;
chomp($radius);

if ($radius < 0) {
    $radius = 0;
}

my $circumference = 2 * 3.14159 * $radius;
print "该圆的周长是: $circumference
";

将上述代码保存为一个

.pl

文件,例如

circle_circumference.pl

,然后在终端中运行

perl circle_circumference.pl

,按照提示输入圆的半径,程序将计算并输出圆的周长。

44、编写一个Perl程序,提示用户输入两个数字,将这两个数字相乘并输出结果

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


#!/usr/bin/perl
print "请输入第一个数字: ";
chomp(my $num1 = <STDIN>);
print "请输入第二个数字: ";
chomp(my $num2 = <STDIN>);
my $result = $num1 * $num2;
print "两数相乘的结果是: $result
";

上述程序首先提示用户输入两个数字,使用

chomp

函数去除输入的换行符,然后将两个数字相乘,最后输出结果。

45、编写一个Perl程序,提示用户输入一个字符串和一个数字,将该字符串重复指定的次数并输出结果,要求字符串出现在不同的行上

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


print "请输入一个字符串: ";
chomp(my $str = <STDIN>);
print "请输入一个数字: ";
chomp(my $num = <STDIN>);
for (my $i = 0; $i < $num; $i++) { 
    print $str, "
";
}

该程序首先提示用户输入一个字符串和一个数字,然后使用

for

循环将字符串重复指定的次数并输出,每次输出后换行。

46、编写一个Perl程序,提示用户输入一些行,然后按相反的顺序输出这些行

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


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

print "请输入一些行,输入结束后按Ctrl+D(Unix/Linux)或Ctrl+Z(Windows):
";

my @lines;
while (<STDIN>) {
    chomp;
    push @lines, $_;
}

foreach (reverse @lines) {
    print $_ . "
";
}

上述程序首先提示用户输入一些行,使用

while (<STDIN>)

循环读取用户输入的每一行,将其存入数组

@lines

中。最后,使用

reverse

函数反转数组元素的顺序,并逐行输出。

47、编写程序,让用户输入一些行,按 Ctrl – D 结束输入,将输入的行排序后输出,分别实现输出在一行和分行输出两种情况

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


lines = []
while True:
    try:
        line = input()
        lines.append(line)
    except EOFError:
        break

# 分行输出
print('分行输出:')
for line in sorted(lines):
    print(line)

# 输出在一行
print('输出在一行:')
print(' '.join(sorted(lines)))

上述代码首先通过循环读取用户输入的行,直到用户按下 Ctrl-D(在Windows中是 Ctrl-Z)引发

EOFError

异常时停止。然后分别实现了分行输出和输出在一行的功能。分行输出时,遍历排序后的行列表并逐行打印;输出在一行时,使用

join

方法将排序后的行列表连接成一个字符串并打印。

48、编写程序,让用户输入一个字符串和一个数字,将字符串重复指定次数输出,字符串要分行显示

以下是使用Python实现的代码:


string = input("请输入一个字符串:")
num = int(input("请输入一个数字:"))
for i in range(num):
    print(string)

这段代码首先通过

input

函数获取用户输入的字符串和数字,将数字转换为整数类型,然后利用

for

循环将字符串重复指定次数并分行输出。

49、编写一个子程序计算传入参数的平均值,再编写一个子程序找出传入参数中大于平均值的元素

以下是使用 Perl 语言实现的代码示例:


# 计算平均值的子程序
sub calculate_average {
    my $sum = 0;
    foreach my $num (@_) {
        $sum += $num;
    }
    return $sum / @_;
}

# 找出大于平均值的元素的子程序
sub find_greater_than_average {
    my $average = calculate_average(@_);
    my @result;
    foreach my $num (@_) {
        if ($num > $average) {
            push @result, $num;
        }
    }
    return @result;
}

# 示例调用
my @numbers = (1, 2, 3, 4, 5);
my $avg = calculate_average(@numbers);
my @greater_than_avg = find_greater_than_average(@numbers);
print "平均值: $avg
";
print "大于平均值的元素: @greater_than_avg
";

这段代码定义了两个子程序,

calculate_average

用于计算传入参数的平均值,

find_greater_than_average

用于找出传入参数中大于平均值的元素。最后进行了示例调用并输出结果。

© 版权声明

相关文章

暂无评论

none
暂无评论...