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;
}
24、编写一个程序,使用 Perl 语言列出命令行中指定的所有可读、可写且归当前用户所有的文件。
使用 Perl 5.10 及以上版本,代码示例如下:
```perl
use 5.010;
die "No files specified!
" unless @ARGV;
foreach my $file ( @ARGV ) {
print "$file is readable, writable and owned by you
" if( -w -r -o $file );
}
若使用 Perl 5.10 之前的版本,代码如下:
print "Looking for my files that are readable and writable
";
die "No files specified!
" unless @ARGV;
foreach my $file ( @ARGV ) {
print "$file is readable and writable
" if( -w $file && -r _ && -o _ );
}
##25、编写一个程序,向用户询问一个目录名,然后切换到该目录。如果用户输入的行只有空白字符,则默认切换到他或她的主目录。切换后,按字母顺序列出普通目录内容(不包括名称以点开头的项目)。(提示:使用目录句柄还是通配符更容易实现?)如果目录切换不成功,只需提醒用户,但不要尝试显示内容。
以下是实现该功能的程序:
```perl
print 'Which directory? (Default is your home directory) ';
chomp(my $dir = <STDIN>);
if ($dir =~ /As*/) {
chdir or die "Can't chdir to your home directory: $!";
} else {
chdir $dir or die "Can't chdir to '$dir': $!";
}
opendir DOT, "." or die "Can't opendir dot: $!";
foreach (sort readdir DOT) {
next if /A./;
print "$_
";
}
closedir DOT; # 补充关闭目录句柄
该程序首先提示用户输入目录名,处理用户输入的空白字符情况以切换到主目录。然后尝试切换到指定目录,若失败则输出错误信息。接着打开当前目录句柄,读取目录内容,过滤掉以点开头的文件,并按字母顺序打印其余文件。使用目录句柄实现该功能相对更方便。
26、编写一个程序,其功能类似于
rm
命令,删除命令行中指定的所有文件。(你不需要处理
rm
的任何选项)
rm
rm
可以使用Perl语言编写如下程序来实现该功能:
#!/usr/bin/perl
use strict;
use warnings;
# 获取命令行参数中的文件名列表
my @files = @ARGV;
# 使用unlink操作符删除文件
unlink @files or warn "无法删除部分文件: $!";
将上述代码保存为一个
.pl
文件,例如
rm_like.pl
,并赋予执行权限:
chmod +x rm_like.pl
然后在命令行中使用
./rm_like.pl file1 file2 ...
的形式来删除指定的文件。
27、编写一个程序,其功能类似于mv命令,将第一个命令行参数重命名为第二个命令行参数。(你不需要处理mv的任何选项或额外参数。)请记住要考虑目标可能是一个目录的情况;如果是目标为目录,则在新目录中使用相同的原始基本名称。
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': $!
";
28、如果你的操作系统支持,编写一个程序来查找当前目录中的任何符号链接,并打印出它们的值(就像使用
ls -l
命令那样:名称 -> 值)。
ls -l
foreach ( glob( '.* *' ) ) {
my $dest = readlink $_;
print "$_ -> $dest
" if defined $dest;
}
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}
";
}
这段代码首先定义了哈希表
%last_name
,然后使用
sort
函数对哈希表的键进行排序。排序规则是先按姓氏的小写形式进行字母顺序排序,如果姓氏相同,则按名字的小写形式排序。最后,遍历排序后的键列表并打印出名字和姓氏。
30、编写一个程序,在给定的字符串中查找给定子字符串的每一次出现,并打印出子字符串出现的位置。例如,给定输入字符串 “This is a test.” 和子字符串 “is”,程序应报告位置 2 和 5。如果子字符串是 “a”,则应报告 8。如果子字符串是 “t”,程序会报告哪些位置?
该程序会报告位置 0、10、13。
31、使用
given
和智能匹配,编写一个程序,报告你在命令行中指定的数字的所有因数(除了1和该数字本身)。例如,对于数字99,你的程序应该报告它能被3、9、11和33整除。如果该数字是质数(没有因数),则报告该数字是质数。如果命令行参数不是数字,报告错误并且不要尝试计算因数。尽管你可以使用
if
结构和普通匹配来完成这个任务,但请仅使用智能匹配。
given
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;
}
该程序首先检查命令行参数是否为数字,如果不是则输出错误信息。如果是数字,它会计算该数字的因数(除了1和该数字本身),如果没有因数则报告该数字是质数,否则报告该数字能被哪些因数整除。
32、编写一个程序,该程序接收一个数字作为输入,报告该数字是奇数还是偶数,该数字是否为质数(除了 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 is in @divisors
say "$_ is even";
continue;
}
when( !( @divisors ~~ 2 ) ) {
# 2 isn't in @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: $!";
34、(仅适用于Unix系统)编写一个无限循环程序,该程序能捕获信号,报告捕获到的信号以及之前看到该信号的次数。如果捕获到INT信号则退出程序。可以使用命令行的kill命令发送信号,例如:$ kill -USR1 12345 ;若不能使用命令行的kill命令,也可编写另一个程序来向它发送信号,比如使用Perl单行命令:$ perl -e ‘kill HUP => 12345’。
以下是实现该功能的代码:
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'
35、编写一个程序,从文件中读取字符串列表,每行一个字符串,然后让用户交互式地输入可能匹配某些字符串的模式。对于每个模式,程序应告知文件中有多少字符串匹配,以及是哪些字符串。不要为每个新模式重新读取文件,将字符串保存在内存中。文件名可以在文件中硬编码。如果模式无效(例如,括号不匹配),程序应简单报告该错误并让用户继续尝试模式。当用户输入空白行而不是模式时,程序应退出。
以下是实现该功能的代码:
# 硬编码文件名,这里假设文件名为'sample_text'
open(my $fh, '<', 'sample_text') or die "Can't open file: $!";
my @strings = <$fh>;
close $fh;
chomp @strings;
while (1) {
print 'Please enter a pattern: ';
chomp(my $pattern = <STDIN>);
last if $pattern =~ /As*/;
my @matches = eval { grep /$pattern/, @strings; };
if ($@) {
print "Error: $@";
} else {
my $count = @matches;
print "There were $count matching strings:
", map "$_", @matches;
}
print "
";
}
此代码首先从文件中读取所有字符串并存储在数组
@strings
中。然后进入一个无限循环,提示用户输入模式。如果用户输入空白行,程序退出。对于每个非空白模式,使用
eval
块来捕获正则表达式可能出现的错误,使用
grep
函数从字符串列表中提取匹配的字符串。如果出现错误,打印错误信息;否则,打印匹配的字符串数量和具体的匹配字符串。
36、编写一个程序,生成当前目录中文件的访问和修改时间(以纪元时间表示)的报告。使用
stat
来获取这些时间,并使用列表切片来提取元素。将结果以三列形式报告,如下所示:fred.txt 1294145029 1290880566 barney.txt 1294197219 1290810036 betty.txt 1287707076 1274433310
stat
以下是一个满足需求的 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、修改练习的答案,使用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!
";
若使用 Perl 5.10 或更高版本,使用
say
:
perl
use 5.010;
say "Hello, world!";
从命令行使用
-e
开关:
bash
$ perl -e 'print "Hello, World
"'
从命令行使用
-l
开关:
bash
$ perl -le 'print "Hello, World"'
39、编写程序计算半径为12.5的圆的周长并输出
以下是使用 Python 语言实现的代码:
import math
radius = 12.5
circumference = 2 * math.pi * radius
print(circumference)
上述代码先导入
math
模块,然后定义半径,接着根据圆的周长公式计算周长,最后将结果输出。
40、编写程序让用户输入圆的半径,然后计算并输出该圆的周长
以下是使用Python语言实现该功能的代码:
import math
radius = float(input("请输入圆的半径:"))
circumference = 2 * math.pi * radius
print("该圆的周长是:", circumference)
上述代码首先导入
math
模块,然后通过
input
函数获取用户输入的半径,并将其转换为浮点数类型。接着,根据圆的周长公式
2 * π * r
计算周长,最后使用
print
函数输出结果。
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
";
这个程序首先提示用户输入圆的半径,然后检查输入的半径是否为负数,如果是则将其设为0,最后计算并输出圆的周长。
44、编写一个Perl程序,提示用户输入两个数字,计算它们的乘积并输出结果
以下是一个满足需求的Perl程序示例:
print "请输入第一个数字: ";
$num1 = <STDIN>;
chomp($num1);
print "请输入第二个数字: ";
$num2 = <STDIN>;
chomp($num2);
$result = $num1 * $num2;
print "这两个数字的乘积是: $result
";
将上述代码保存为一个
.pl
文件,例如
product.pl
,然后在命令行中运行
perl product.pl
即可。程序会提示你输入两个数字,输入后会计算并输出它们的乘积。
45、编写一个Perl程序,提示用户输入一个字符串和一个数字,将字符串重复指定的次数并输出结果,要求字符串每次重复后换行
以下是实现该功能的 Perl 程序:
#!/usr/bin/perl
print "请输入一个字符串: ";
my $string = <STDIN>;
chomp($string);
print "请输入一个数字: ";
my $num = <STDIN>;
chomp($num);
for (my $i = 0; $i < $num; $i++) {
print $string . "
";
}
将上述代码保存为一个
.pl
文件,例如
repeat_string.pl
,然后在终端中运行
perl repeat_string.pl
,按照提示输入字符串和数字,程序将输出重复指定次数的字符串,每次重复后换行。
46、编写一个Perl程序,提示用户输入多行内容,按Ctrl – D(或Ctrl – Z)结束输入,然后将输入的行逆序输出
以下是实现该功能的Perl程序:
#!/usr/bin/perl
use warnings;
use strict;
print "请输入多行内容,按Ctrl - D(或Ctrl - Z)结束输入:
";
my @lines;
while (my $line = <STDIN>) {
chomp $line;
push @lines, $line;
}
foreach my $line (reverse @lines) {
print $line, "
";
}
将上述代码保存为一个
.pl
文件,例如
reverse_lines.pl
,然后在终端中运行
perl reverse_lines.pl
,按照提示输入内容,按 Ctrl – D(或 Ctrl – Z)结束输入,程序将逆序输出输入的行。