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

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

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


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 "$_";
}

程序首先提示用户输入目录名,对输入进行处理。若输入为空,则切换到主目录;否则切换到用户指定的目录。若切换失败,程序会输出错误信息并终止。最后,使用通配符

<(*)>

获取目录中的普通文件(非以点开头),对结果排序后逐个输出。

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

rm

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

rm

命令的任何选项。)

在 Perl 中,可以使用

unlink

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


unlink @ARGV;

或者逐一遍历文件删除并处理可能的错误:


foreach my $file (@ARGV) {
    unlink $file or warn "failed on $file: $!";
}

其中

@ARGV

是 Perl 中存储命令行参数的数组。

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、编写一个程序,允许在其他参数之前使用一个可选的 -s 开关,以表明要创建一个软链接而不是硬链接。若目标路径是一个目录,则将源文件的基本名称添加到该目录路径后作为目标路径。若系统支持,要能正常创建硬链接和软链接;即使系统没有硬链接,也至少要能创建软链接。


my $symlink = $ARGV[0] eq '-s';
shift @ARGV if $symlink;
my($source, $dest) = @ARGV;

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

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': $!
";
}

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

ls -l

那样:名称 -> 值)。


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

30、编写一个程序,读入一组数字,对它们进行数值排序,并将排序后的结果以右对齐的列形式输出。用以下示例数据进行测试: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
", $_; }

将上述代码保存为一个

.pl

文件,例如

sort_numbers.pl

,然后在命令行中运行:


perl sort_numbers.pl <<< "17 1000 04 1.50 3.14159 -10 1.5 4 2001 90210 666"

代码解释:

while (<>)

循环逐行读取输入,

split

函数默认按空白字符分割每行,将结果存入

@numbers

数组。

sort {$a <=> $b} @numbers


@numbers

数组进行数值排序。

foreach

循环遍历排序后的数组,使用

printf "%20g
", $_

以右对齐的列形式输出每个数字。

31、编写一个程序,将以下哈希表的数据按姓氏进行不区分大小写的字母顺序排序。当姓氏相同时,再按名字(同样不区分大小写)排序。输出中的第一个名字应该是 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};
sub case_insensitive_sort {
    my $last_a = lc($last_name{$a});
    my $last_b = lc($last_name{$b});
    my $first_a = lc($a);
    my $first_b = lc($b);
    return $last_a cmp $last_b || $first_a cmp $first_b;
}
my @sorted_names = sort case_insensitive_sort keys %last_name;
foreach my $name (@sorted_names) {
    print "$name $last_name{$name}
";
}

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

程序会报告位置10和13。

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

ls -l

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

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


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

该程序首先尝试切换到系统的根目录,如果切换失败则输出错误信息并终止程序。然后执行

ls -l

命令来获取长格式的目录列表,如果执行失败同样输出错误信息并终止程序。

34、修改上一个程序,将命令的输出发送到当前目录下名为 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: $!";

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

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


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

# 获取日期输出
my $date_output = `date`; # 如果是Windows且无date命令,可使用print localtime( ) . "
"输出的内容

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

该程序首先执行

date

命令获取日期输出,然后使用正则表达式匹配输出的开头部分,判断是否为工作日并输出相应信息。对于非Unix系统且无

date

命令的情况,可将

$date_output

赋值为

print localtime( ) . "
"

输出的内容。

36、编写一个仅适用于Unix系统的无限循环程序,该程序能捕获信号,报告捕获到的信号以及此前看到该信号的次数。如果捕获到INT信号则退出程序。若可以使用命令行的kill命令,可通过 $ kill -USR1 12345 发送信号;若无法使用命令行的kill命令,需编写另一个程序来发送信号,也可使用Perl单行命令:$ perl -e ‘kill HUP => 12345’。

以下是满足要求的Perl代码示例:


my %signal_count;
foreach my $signal (qw(int hup usr1 usr2)) {
    $SIG{ uc $signal } = sub {
        my $sig_name = uc $signal;
        $signal_count{$sig_name}++;
        print "Caught $sig_name: $signal_count{$sig_name}";
        if ($sig_name eq 'INT') {
            print ". Exiting.
";
            exit;
        }
        print "
";
    };
}
print "I am $$
";
while(1) {
    sleep 1;
}

上述代码中,定义了一个哈希表

%signal_count

来记录每个信号的捕获次数。通过

foreach

循环为

int


hup


usr1


usr2

信号设置信号处理函数。在信号处理函数中,对信号捕获次数进行累加并打印相关信息,若捕获到

INT

信号则退出程序。最后程序进入无限循环,每秒休眠一次等待信号到来。

37、编写一个程序,报告当前目录中文件的访问时间和修改时间(以纪元时间表示)。使用 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;
}

38、修改代码,将纪元时间转换为YYYY – MM – DD格式的日期字符串并报告。使用带有localtime和切片的map进行转换。报告格式如下:文件名 访问时间 修改时间,例如: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;
}

39、如何让以下程序正常运行:print “Hello, world!
”; 如果你使用的是 v5.10 或更高版本,可以尝试使用 say:use v5.10; say “Hello, world!”; 你也可以使用相关开关从命令行尝试运行。

若要让

print "Hello, world!
";

运行,可将其保存为

.pl

文件,如

test.pl

,然后在命令行输入

perl test.pl

运行。若有 v5.10 或更高版本,可将

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

保存为文件运行,也可在命令行使用

-E

开关:


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

还可使用

-e

开关运行

print

语句:


perl -e 'print "Hello, world!
"'

使用

-l

开关自动添加换行符:


perl -le 'print "Hello, world!"'

在 Windows 的

command.exe


cmd.exe

中,引号使用方式不同,如:


perl -le "print 'Hello, world!'"

也可使用广义引号:


perl -le "print q(Hello, world!)"

40、运行 perldoc 命令。如果你找不到 perldoc,找出解决办法。

perldoc

命令通常随 Perl 一起提供,你应该能够直接运行它。如果你找不到

perldoc

,可能需要在系统上安装另一个软件包,例如在 Ubuntu 系统中,它包含在

perl-doc

软件包中。

41、让以下程序正常运行:@lines =

perldoc -u -f atan2

; foreach (@lines) { s/w<([^>]+)>U$1/g; print; }

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

原代码中

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

存在错误,正确的应该是

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

,修改后的完整代码如下:


@lines = `perldoc -u -f atan2`;
foreach (@lines) {
    s/w<([^>]+)>/U$1/g;
    print;
}

同时要确保系统中

perldoc

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

42、编写一个程序来计算并打印半径为 12.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.
";

43、编写程序计算半径为 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

计算周长,将结果存储在变量

$circumference

中,最后使用

print

函数输出结果。这里 π 取值为 3.14159。

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

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


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

上述代码中,首先导入了

math

模块,它提供了数学相关的函数和常量,其中就包括圆周率

pi

。接着使用

input

函数获取用户输入的半径,并将其转换为浮点数类型。然后根据圆的周长公式

2 * π * r

计算圆的周长。最后使用

print

函数输出计算得到的圆的周长。

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

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


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

上述代码首先导入

math

模块以使用圆周率

pi

,接着获取用户输入的半径,然后判断半径是否为负数,若为负数则将周长设为 0,否则根据公式计算周长,最后输出圆的周长。

46、编写程序让用户输入两个数字,计算并输出它们的乘积

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


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

这段代码首先使用

input

函数获取用户输入的两个数字,然后将输入的字符串转换为浮点数,接着计算它们的乘积,最后使用

print

函数输出结果。

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

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


string = input("请输入一个字符串:")
num = int(input("请输入一个数字:"))
result = string * num
print(result)

上述代码会提示用户输入一个字符串和一个数字,然后将字符串重复指定的次数并输出结果。

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

以下是一个使用 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)

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

49、编写代码实现:提示用户输入一些行,然后按 Ctrl – D(或 Ctrl – Z),最后反向输出这些行

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


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

my @lines;

print "请输入一些行,按 Ctrl-D(或 Ctrl-Z)结束输入:
";

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

foreach my $line (reverse @lines) {
    print $line, "
";
}

上述代码首先提示用户输入一些行,按 Ctrl-D(或 Ctrl-Z)结束输入。然后将用户输入的每一行存储在数组

@lines

中,最后反向遍历该数组并输出每一行。

© 版权声明

相关文章

暂无评论

none
暂无评论...