Perl编程实例解析与实现

内容分享2天前发布
0 0 0

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

26、编写一个程序,允许在其他参数之前使用一个可选的 -s 开关,以表明要创建一个软链接而不是硬链接。若目标路径是目录,则将源文件的基本名称添加到该目录路径后作为目标路径。即使系统没有硬链接,也尝试用这个程序创建软链接。


my $symlink = $ARGV[0] eq '-s';
shift @ARGV if $symlink;

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

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

if ($symlink) {
    symlink $source, $dest
        or die "Can't make soft link from '$source' to '$dest': $!
";
} else {
    link $source, $dest
        or die "Can't make hard link from '$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 代码:


while (<>) {
    push @numbers, split;
}

my @sorted_numbers = sort {$a <=> $b} @numbers;

foreach (@sorted_numbers) {
    printf "%20g
", $_;
}

将上述示例数据保存为一个文本文件,例如

data.txt

,然后在命令行中运行:


perl your_script.pl data.txt

即可看到排序并右对齐输出的结果。

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

程序会报告位置10和13。

30、编写一个程序,切换到某个特定的(硬编码的)目录,比如系统的根目录,然后执行

ls -l

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

以下为示例代码:


open STDOUT, '>', 'ls.out' or die "Can't write to ls.out: $!";
open STDERR, '>', 'ls.err' or die "Can't write to ls.err: $!";
chdir '/' or die "Can't chdir to root directory: $!";
exec 'ls', '-l' or die "Can't exec ls: $!";

代码解释:前两行将标准输出和标准错误重定向到当前目录下的文件,接着切换到根目录,最后执行

ls -l

命令。若执行失败,会输出相应的错误信息。

31、修改上一个程序,将命令的输出发送到当前目录下名为 ls.out 的文件中。错误输出应发送到名为 ls.err 的文件中。(你无需对这两个文件可能为空的情况做特殊处理)


open STDOUT, '>', 'ls.out' or die "Can't write to ls.out: $!";
open STDERR, '>', 'ls.err' or die "Can't write to ls.err: $!";
chdir '/' or die "Can't chdir to root directory: $!";
exec 'ls', '-l' or die "Can't exec ls: $!";

32、(仅适用于Unix系统)编写一个无限循环程序,该程序能捕获信号,报告捕获到的信号以及此前该信号被捕获的次数。若捕获到INT信号则退出程序。若能使用命令行的kill命令,可以像这样发送信号:$ kill -USR1 12345;若不能使用命令行的kill命令,编写另一个程序来发送信号,可使用Perl单行命令:$ perl -e ‘kill HUP => 12345’。

示例程序如下:


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

需要在另一个终端会话中运行程序发送信号,例如:


$ kill -HUP 61203
$ perl -e 'kill HUP => 61203'
$ perl -e 'kill USR2 => 61203'

程序输出会显示捕获到信号的运行计数,如:


$ perl signal_catcher
I am 61203
Caught HUP: 1
Caught HUP: 2
Caught USR2: 1
Caught HUP: 3
Caught USR2: 2
Caught INT. Exiting.

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

可以使用以下代码实现:


foreach ( glob( '*' ) ) {
    my( $atime, $mtime ) = (stat)[8,9];
    printf "%-20s %10d %10d
", $_, $atime, $mtime;
}

或者使用自定义控制变量:


foreach my $file ( glob( '*' ) ) {
    my( $atime, $mtime ) = (stat $file)[8,9];
    printf "%-20s %10d %10d
", $file, $atime, $mtime;
}

34、使用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;
}

35、如何运行程序 print “Hello, world!
”; ?若有 v5.10 或以后版本有什么更简便的方式?怎样在命令行运行该程序且不创建文件?

若要运行程序

print "Hello, world!
";

,若有 v5.10 或更高版本,可使用以下代码:


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

若想在命令行运行且不创建文件,可使用

-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

36、运行 perldoc 命令,若找不到该命令,需要怎么做?

若找不到

perldoc

命令,可能需要在系统上安装其他包。例如在 Ubuntu 系统中,需安装

perl-doc

包。

37、运行程序@lines =

perldoc -u -f atan2

; foreach (@lines) { s/w<([^>]+)>/U$1/g; print; },请描述该程序的执行过程和可能出现的情况。

该程序首先运行外部命令

perldoc -u -f atan2

,将其输出保存到数组变量

@lines

中。然后通过循环处理

@lines

中的每一行,使用正则表达式

s/w<([^>]+)>/U$1/g

对每行进行修改,最后打印出修改后的行。

运行结果应与单独执行

perldoc -u -f atan2

类似,但在有特殊标记处会有改变。


perldoc

不可用,可能是系统没有命令行界面,或该命令包含在不同的软件包中。

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

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


import math
radius = 12.5
circumference = 2 * math.pi * radius
print(circumference)

在Perl语言中可使用如下代码:


my $radius = 12.5;
my $circumference = 2 * 3.1415926 * $radius;
print $circumference, "
";

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

在Perl中可以这样编写程序来计算半径为12.5的圆的周长:


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

my $radius = 12.5;
my $circumference = 2 * 3.14159 * $radius;
print "半径为 12.5 的圆的周长是: $circumference
";

上述代码首先定义了半径变量

$radius

为 12.5,然后根据圆的周长公式

C = 2πr

计算周长,最后将结果输出。这里 π 取 3.14159。

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

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


import math
# 获取用户输入的半径
radius = float(input("请输入圆的半径: "))
# 计算圆的周长
circumference = 2 * math.pi * radius
# 输出结果
print("该圆的周长是", circumference)

此代码首先导入

math

模块,之后获取用户输入的半径,接着依据圆的周长公式

2 * π * 半径

算出周长,最后输出结果。

41、编写程序,让用户输入圆的半径,计算并输出该圆的周长,同时要检查输入的半径是否为负数,如果是负数,输出的周长为 0

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


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

上述代码首先导入

math

模块,通过

input

函数获取用户输入的半径并转换为浮点数。接着检查半径是否为负数,若是则将周长设为 0,否则根据圆的周长公式计算周长。最后使用

print

函数输出圆的周长。

42、编写程序,让用户输入两个数字,然后输出这两个数字的乘积

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


num1 = float(input('请输入第一个数字: '))
num2 = float(input('请输入第二个数字: '))
product = num1 * num2
print('这两个数字的乘积是:', product)

该程序首先使用

input

函数获取用户输入的两个数字,将其转换为浮点数类型,然后计算它们的乘积并输出结果。

43、编写程序,让用户输入一个字符串和一个数字,然后将该字符串重复指定的次数并输出

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


print "请输入一个字符串: ";
chomp(my $input_string = <STDIN>);
print "请输入重复的次数: ";
chomp(my $repeat_count = <STDIN>);
my $result = $input_string x $repeat_count;
print "重复后的字符串是: $result
";

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

x

操作符将字符串重复指定的次数,并将结果输出。

44、编写程序,让用户输入一些行,然后将这些行反转并输出

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


lines = []
while True:
    try:
        line = input()
        if not line:
            break
        lines.append(line)
    except EOFError:
        break
reversed_lines = lines[::-1]
for line in reversed_lines:
    print(line)

此代码会持续读取用户输入的行,直到遇到空行或文件结束符,然后反转这些行并逐行输出。

45、编写程序,定义一个包含七个名字的数组,让用户输入 1 到 7 之间的数字,然后输出对应索引位置的名字

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


names = ['张三', '李四', '王五', '赵六', '孙七', '周八', '吴九']
while True:
    try:
        num = int(input('请输入 1 到 7 之间的数字:'))
        if 1 <= num <= 7:
            print(names[num - 1])
            break
        else:
            print('输入的数字不在 1 到 7 范围内,请重新输入。')
    except ValueError:
        print('输入无效,请输入一个整数。')

这段代码首先定义了一个包含七个名字的数组

names

,然后通过

input

函数获取用户输入的数字,将其转换为整数后进行判断,如果输入的数字在 1 到 7 范围内,则输出对应索引位置的名字,否则提示用户重新输入。如果输入的不是有效的整数,会捕获

ValueError

异常并提示用户输入有效的整数。

46、编写代码实现读取用户输入的多行内容,然后逆序输出这些内容

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


lines = []
while True:
    line = input()
    if not line:
        break
    lines.append(line)
for line in reversed(lines):
    print(line)

上述代码首先创建一个空列表

lines

用于存储用户输入的每一行内容。通过一个无限循环不断读取用户输入,当用户输入空行时,循环结束。最后,使用

reversed

函数将列表

lines

逆序,并逐行输出。

47、有一个包含名字的数组 @names = qw/ fred betty barney dino wilma pebbles bamm – bamm /,编写代码让用户输入 1 到 7 的数字,根据输入的数字输出对应的名字

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


@names = qw/ fred betty barney dino wilma pebbles bamm - bamm /;
print "请输入 1 到 7 的数字:";
$input = <STDIN>;
chomp($input);
if ($input >= 1 && $input <= 7) {
    print $names[$input - 1]. "
";
} else {
    print "输入的数字不在 1 到 7 的范围内。
";
}

这段代码首先定义了包含名字的数组

@names

,然后提示用户输入 1 到 7 的数字,接着检查输入的数字是否在有效范围内,如果是则输出对应的名字,否则提示输入无效。

48、编写代码对用户输入的多行内容进行排序并输出,要求分别实现输出在一行和分行输出两种情况

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


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

# 提示用户输入多行内容
print "请输入多行内容,输入结束后按 Ctrl+D(Unix/Linux)或 Ctrl+Z(Windows):
";

my @lines;

# 读取用户输入的多行内容
while (my $line = <STDIN>) {
    chomp $line;
    push @lines, $line;
}

# 对内容进行排序
my @sorted_lines = sort @lines;

# 输出在一行
print "一行输出:", join(" ", @sorted_lines), "
";

# 分行输出
print "分行输出:
";
foreach my $line (@sorted_lines) {
    print $line, "
";
}

上述代码首先提示用户输入多行内容,将输入的内容存储在数组中,然后对数组进行排序。接着分别实现了将排序后的内容输出在一行和分行输出的功能。

49、编写一个子例程 sub total 来计算传入参数的总和


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

50、编写一个子程序来计算参数列表中所有数字的总和。如果参数列表为空,考虑返回值的设置问题。

以下是一个用 Perl 编写的子程序来实现计算参数列表中所有数字的总和,当参数列表为空时返回 0:


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

你可以使用以下方式调用这个子程序:


my $result = sum_numbers(1, 2, 3, 4);
print $result; # 输出 10
my $empty_result = sum_numbers();
print $empty_result; # 输出 0

51、编写两个子程序,一个计算参数列表的平均值,另一个返回参数列表中大于平均值的元素组成的列表。

以下是使用 Perl 语言实现的两个子程序:


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

# 返回大于平均值的元素组成的列表的子程序
sub above_average {
    my $avg = average(@_);
    my @result;
    foreach my $num (@_) {
        if ($num > $avg) {
            push @result, $num;
        }
    }
    return @result;
}

你可以使用以下方式调用这两个子程序:


my @numbers = (1, 2, 3, 4, 5);
my $avg = average(@numbers);
my @above_avg = above_average(@numbers);

print "平均值: $avg
";
print "大于平均值的元素: @above_avg
";

52、编写一个

greet

子程序,使用状态变量记住最后一个打招呼的人,并在每次调用时输出相应信息。


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' );

53、编写一个名为

greet

的子程序,使用状态变量存储所有打过招呼的人的名字,并在每次调用该子程序时输出相应信息。例如,当第一次调用时,若传入名字 ‘Fred’,输出 ‘Hi Fred! You are the first one here!’;后续调用时,若传入名字 ‘Barney’,输出 ‘Hi Barney! I’ve seen: Fred’ 。


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;
}
© 版权声明

相关文章

暂无评论

none
暂无评论...