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

26、编写一个程序,使用堆叠文件测试运算符列出命令行中指定的所有可读、可写且由你拥有的文件。

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


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

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

将上述代码保存为一个

.pl

文件,例如

test.pl

,然后在命令行中运行

perl test.pl file1 file2 ...

,其中

file1 file2 ...

是你要测试的文件名。程序会列出所有可读、可写且由你拥有的文件。

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

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


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

上述代码首先提示用户输入目录名,若用户输入空白行则切换到主目录,否则切换到用户指定的目录。然后使用通配符

<*>

获取普通目录内容(不包含以点开头的文件),最后对结果进行排序并逐行输出。如果目录切换失败,程序会输出错误信息并终止。

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

rm

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

rm

命令的任何选项)

在 Perl 中可以使用以下代码实现:


foreach my $file (@ARGV) {
    unlink $file or warn "无法删除 $file: $!";
}

上述代码遍历命令行参数中的每个文件,使用

unlink

函数尝试删除文件,如果删除失败则输出警告信息。

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

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

30、编写一个程序,允许在其他参数之前使用可选的 -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': $!
";
}

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

ls -l

那样:名称 -> 值)。

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


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

此代码通过

glob

函数获取当前目录下的所有文件和文件夹(包括隐藏文件),然后使用

readlink

函数尝试读取每个文件或文件夹的符号链接目标。如果

readlink

函数返回一个定义的值(即该文件或文件夹是符号链接),则打印出符号链接的名称和目标。

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

10、13

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

ls -l

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


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

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`; # 如果是非Unix系统,可使用 print localtime( ). "
" 替代

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

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

36、修改练习,使用YYYY – MM – DD格式报告时间。使用map和localtime以及切片将纪元时间转换为所需的日期字符串。注意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;
}

37、运行程序 print “Hello, world!
”; ,若有 v5.10 或更高版本,尝试使用 say;若想从命令行运行而不创建文件,使用 -e 开关指定程序,同时了解 -l、-E 等开关的使用,使程序正常运行。

运行

print "Hello, world!
";

:在编写好包含该语句的 Perl 脚本文件(如

test.pl

)后,在命令行执行

perl test.pl

若有 v5.10 或更高版本,使用

say

:在脚本中添加

use v5.10;

,然后使用

say "Hello, world!";

,保存为文件后执行

perl 文件名

从命令行运行而不创建文件,使用

-e

开关指定程序:

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

-l

开关使用:

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


此开关会自动添加换行符。在 Windows 的

command.exe

(或

cmd.exe

)中,引号使用方式为:

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


也可使用广义引号:

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

-E

开关使用:v5.10 及更高版本,使用

-E

开关启用新特性,允许使用

say

,如:

bash
$ perl -E 'say "Hello, World"'

38、运行 perldoc 命令,若找不到 perldoc,应该怎么做?

若运行

perldoc

命令时找不到

perldoc

,可能需要在系统上安装相应的包,例如在 Ubuntu 系统中,需安装

perl-doc

包。

39、编写一个Perl程序,该程序将

perldoc -u -f atan2

命令的输出结果中的

w<...>

形式的内容替换为

U

加上尖括号内的内容(字母转换为大写),并将处理后的结果输出。

可直接编写如下程序:


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

将上述代码保存为一个

.pl

文件,例如

test.pl

,然后在命令行中运行

perl test.pl

即可。

40、编写程序计算半径为 12.5 的圆的周长并输出结果,可使用 $pi = 3.141592654 或使用 π 字符作为变量名(需告知 Perl 源代码包含 Unicode 字符)。


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

方法二:


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

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

即可得到结果。

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

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


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

上述代码首先导入

math

模块以使用圆周率

pi

,接着通过

input

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

2 * π * r

计算周长,最后使用

print

函数输出结果。

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

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


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

以上代码首先让用户输入圆的半径,接着检查半径是否为负数,若为负数则将周长设为 0,否则根据公式计算周长并输出。

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

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


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

若使用其他编程语言,实现思路类似,先获取用户输入的两个数字,将其转换为合适的数值类型,然后计算乘积并输出。

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

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


use v5.10;
print "请输入一个字符串: ";
chomp(my $str = <STDIN>);
print "请输入一个数字: ";
chomp(my $num = <STDIN>);
my $result = $str x $num;
print "重复后的字符串是: $result
";

在上述代码中,首先提示用户输入一个字符串,接着提示用户输入一个数字,然后使用

x

运算符将字符串重复指定的次数,最后输出重复后的字符串。

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

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


my @lines;
while(<STDIN>){ chomp; push @lines, $_; }
foreach my $line (reverse @lines) { print $line, "
"; }

这段代码的逻辑是:先创建一个空数组

@lines

,通过

while(<STDIN>)

循环逐行读取用户输入,使用

chomp

去除每行末尾的换行符,将每行内容存入数组

@lines

中。最后使用

reverse

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

47、编写程序,让用户输入一些行,将这些行排序后输出,分别实现输出在一行和分行输出的版本

以下是使用Perl实现的代码,用于接收用户输入的多行内容,将这些行排序后分别以一行和分行的形式输出:


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

# 存储用户输入的行
my @lines;

# 提示用户输入行,直到用户输入空行
print "请输入一些行,输入空行结束输入:
";
while (my $line = <STDIN>) {
    chomp $line;
    last if $line eq '';
    push @lines, $line;
}

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

# 输出在一行
my $one_line_output = join(" ", @sorted_lines);
print "排序后在一行输出:$one_line_output
";

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

代码解释:


输入处理

:使用

while

循环读取用户输入的每一行,直到用户输入空行。将每行内容存储在数组

@lines

中。


排序

:使用

sort

函数对数组

@lines

进行排序,结果存储在

@sorted_lines

中。


一行输出

:使用

join

函数将排序后的数组元素用空格连接成一个字符串,然后输出。


分行输出

:使用

foreach

循环遍历排序后的数组,逐行输出每个元素。

使用方法:

将上述代码保存为一个

.pl

文件,例如

sort_lines.pl

,然后在终端中运行:


perl sort_lines.pl

按照提示输入一些行,输入空行结束输入,程序将输出排序后的结果,分别以一行和分行的形式展示。

48、编写程序,让用户输入一些行,按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)。然后对输入的行进行排序,分别以分行和一行的形式输出排序后的结果。

49、编写一个名为total的子程序,用于计算传入参数列表的总和。

以下是使用 Perl 语言编写的实现此功能的代码:


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

在上述代码中,定义了一个名为

total

的子程序,它接收一个参数列表。在子程序内部,使用

foreach

循环遍历参数列表,并将每个参数累加到变量

$sum

中,最后返回总和。

50、编写一个子程序来计算参数列表的平均值,再编写一个子程序找出参数列表中大于平均值的元素

可编写两个子程序来实现该需求:


计算平均值的子程序

:通过将参数总和除以参数数量得到平均值。


找出大于平均值元素的子程序

:调用计算平均值的子程序得到平均值,再遍历参数列表找出大于该平均值的元素。

示例代码如下:


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

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

# 测试程序
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
";
print "(Should be just 100)
";

51、编写一个子程序greet,使用状态变量记住最后一个被问候的人

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


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( 'Barney' );
© 版权声明

相关文章

暂无评论

none
暂无评论...