Perl编程技巧与文件操作实践

74、对前一个程序进行修改,当变量 $Debug 为真时打印出秘密数字,$Debug 的值可以是环境变量 $ENV{DEBUG} 的值,若 $ENV{DEBUG} 未定义则默认为 1,分别用 v5.10 及之前的特性实现。

使用 v5.10 特性实现:


use v5.10;
my $Debug = $ENV{DEBUG} // 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Debug;

使用 v5.10 之前特性实现:


my $Debug = defined $ENV{DEBUG} ? $ENV{DEBUG} : 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Debug;

75、编写一个程序,设置一些环境变量,其中键 ZERO 和 EMPTY 有假但已定义的值,键 UNDEFINED 无值。使用 // 运算符在 printf 参数列表中仅当 $ENV{$key} 未定义时选择字符串 (undefined) 进行输出,再用 Perl 5.10 之前的方法实现同样功能。

使用 Perl 5.10 实现的代码如下:


use v5.10;
$ENV{ZERO} = 0;
$ENV{EMPTY} = '';
$ENV{UNDEFINED} = undef;
my $longest = 0;
foreach my $key ( keys %ENV ) {
    my $key_length = length( $key );
    $longest = $key_length if $key_length > $longest;
}
foreach my $key ( sort keys %ENV ) {
    printf "%-${longest}s %s
", $key, $ENV{$key} // "(undefined)";
}

使用 Perl 5.10 之前的方法实现同样功能的代码如下:


$ENV{ZERO} = 0;
$ENV{EMPTY} = '';
$ENV{UNDEFINED} = undef;
my $longest = 0;
foreach my $key ( keys %ENV ) {
    my $key_length = length( $key );
    $longest = $key_length if $key_length > $longest;
}
foreach my $key ( sort keys %ENV ) {
    printf "%-${longest}s %s
", $key, defined $ENV{$key} ? $ENV{$key} : "(undefined)";
}

76、编写程序,找出命令行传入文件中最旧的文件,并打印其文件名和年龄(以天为单位,保留一位小数)

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


die "No file names supplied!" unless @ARGV;
my $oldest_name = shift @ARGV;
my $oldest_age = -M $oldest_name;
foreach (@ARGV) {
    my $age = -M;
    ($oldest_name, $oldest_age) = ($_, $age) if $age > $oldest_age;
}
printf "The oldest file was %s, and it was %.1f days old.
", $oldest_name, $oldest_age;

该程序首先检查命令行是否传入文件名,若未传入则报错退出。接着将第一个文件设为当前最旧文件,记录其年龄。然后遍历其余文件,若某文件的年龄大于当前最旧文件的年龄,则更新最旧文件的信息。最后使用

printf

打印最旧文件的文件名和年龄,年龄保留一位小数。

77、编写程序,在命令行传入的文件中找出自己拥有的、可读且可写的文件并打印,要求使用堆叠文件测试运算符(使用Perl 5.10或更高版本)

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


use v5.10;
foreach my $file (@ARGV) {
    if (-O -r -w $file) {
        say $file;
    }
}

此程序使用了堆叠文件测试运算符

-O

(检查文件是否为当前用户所拥有)、

-r

(检查文件是否可读)和

-w

(检查文件是否可写)。它会遍历命令行传入的所有文件,找出满足条件的文件并打印其名称。

运行该程序时,需在命令行传入文件列表,例如:


perl script.pl file1.txt file2.txt

78、编写程序,提示用户输入一个目录名(默认为用户主目录),然后列出该目录下的所有文件

以下是一个用Python编写的示例程序,它会提示用户输入一个目录名,若用户未输入则使用用户主目录,最后列出该目录下的所有文件:


import os
import pathlib

# 获取用户主目录
home_dir = str(pathlib.Path.home())

# 提示用户输入目录名
input_dir = input(f'请输入目录名(默认为用户主目录:{home_dir}):')

# 如果用户未输入,使用主目录
if not input_dir:
    input_dir = home_dir

# 检查目录是否存在
if os.path.exists(input_dir) and os.path.isdir(input_dir):
    # 列出目录下的所有文件
    files = os.listdir(input_dir)
    for file in files:
        print(file)
else:
    print('输入的目录不存在。')

将上述代码保存为一个Python文件(例如

list_files.py

),在命令行中运行

python list_files.py

,按照提示输入目录名即可查看该目录下的所有文件。

79、编写程序,提示用户输入一个目录名(默认为用户主目录),然后列出该目录下的所有文件(包括以点开头的隐藏文件),并按字母顺序排序

以下是一个使用Perl编写的程序来实现该功能:


#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions qw(canonpath);
use File::HomeDir;

# 获取用户主目录
my $home_dir = File::HomeDir->my_home;

# 提示用户输入目录名,默认为用户主目录
print "请输入一个目录名(默认为用户主目录):";
my $input = <STDIN>;
chomp($input);
my $dir = $input ? canonpath($input) : $home_dir;

# 检查目录是否存在
if (-d $dir) {
    opendir(my $dh, $dir) or die "无法打开目录 $dir: $!";
    my @files = readdir($dh);
    closedir($dh);

    # 按字母顺序排序
    @files = sort @files;

    # 输出文件列表
    foreach my $file (@files) {
        print "$file
";
    }
} else {
    print "指定的目录 $dir 不存在。
";
}

将上述代码保存为一个

.pl

文件,例如

list_files.pl

,然后在终端中运行

perl list_files.pl

,程序会提示你输入目录名,若不输入则默认使用用户主目录,最后列出该目录下的所有文件并按字母顺序排序。

80、编写一个程序,提示用户输入一个目录名(默认是用户的主目录),然后列出该目录下的所有文件。

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


#!/usr/bin/perl
use strict;
use warnings;
use File::HomeDir;

# 获取用户主目录
my $default_dir = File::HomeDir->my_home;

# 提示用户输入目录名
print "请输入目录名(默认为 $default_dir):";
my $input = <STDIN>;
chomp $input;

# 如果用户未输入,则使用默认目录
my $dir = $input ? $input : $default_dir;

# 检查目录是否存在
if (-d $dir) {
    # 打开目录
    opendir(my $dh, $dir) or die "无法打开目录 $dir: $!";

    # 读取目录下的所有文件和文件夹
    my @files = readdir($dh);

    # 关闭目录
    closedir($dh);

    # 输出文件列表
    foreach my $file (@files) {
        next if ($file eq '.' || $file eq '..');
        print "$file
";
    }
} else {
    print "指定的目录 $dir 不存在。
";
}

该程序首先获取用户的主目录作为默认值。接着提示用户输入目录名,如果用户未输入则使用默认目录。然后检查目录是否存在,若存在则打开目录、读取其中的文件和文件夹,并输出文件列表;若不存在则给出相应提示。

81、编写一个程序,提示用户输入一个目录名(默认是用户的主目录),然后列出该目录下的所有文件,包括以点开头的文件。

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


import os
import pathlib

# 获取用户主目录
home_dir = str(pathlib.Path.home())

# 提示用户输入目录名,默认是主目录
dir_name = input(f'请输入目录名(默认是 {home_dir}):')
if not dir_name:
    dir_name = home_dir

# 检查目录是否存在
if os.path.exists(dir_name) and os.path.isdir(dir_name):
    # 列出目录下的所有文件,包括以点开头的文件
    files = os.listdir(dir_name)
    for file in files:
        print(file)
else:
    print(f'指定的目录 {dir_name} 不存在。')

将上述代码保存为一个 Python 文件(例如

list_files.py

),然后在命令行中运行

python list_files.py

,按照提示输入目录名即可列出该目录下的所有文件。

82、编写一个程序,提示用户输入一个目录名(默认是用户的主目录),使用目录句柄打开该目录并列出其中的所有文件。

以下是一个用 Perl 语言编写的示例程序,它可以提示用户输入一个目录名,若用户未输入则使用主目录,然后使用目录句柄打开该目录并列出其中的所有文件:


#!/usr/bin/perl
use strict;
use warnings;
use File::HomeDir;

# 获取用户主目录
my $default_dir = File::HomeDir->my_home;

# 提示用户输入目录名
print "请输入一个目录名(按回车使用默认主目录:$default_dir):";
my $input = <STDIN>;
chomp $input;

# 若用户未输入,使用默认主目录
my $dir = $input ? $input : $default_dir;

# 打开目录
opendir(my $dh, $dir) or die "无法打开目录 $dir: $!";

# 列出目录中的所有文件
while (my $file = readdir($dh)) {
    next if $file eq '.' or $file eq '..'; # 跳过当前目录和上级目录
    print "$file
";
}

# 关闭目录
closedir($dh);

将上述代码保存为一个

.pl

文件,比如

list_files.pl

,然后在终端中运行

perl list_files.pl

即可。程序会提示你输入目录名,若直接回车则使用主目录,接着会列出该目录下的所有文件。

83、编写一个程序,删除命令行参数指定的所有文件,并在删除失败时给出警告信息。

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


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

此程序会遍历命令行参数里的所有文件,尝试删除它们。若删除失败,会使用

warn

函数输出警告信息,其中

$!

会显示具体的错误信息。

84、编写一个程序,将命令行参数指定的源文件重命名为目标文件,如果目标是一个目录,则将源文件移动到该目录下。

可以使用以下示例代码实现该功能(以 Perl 语言为例):


use File::Basename;

if (@ARGV != 2) {
    die "Usage: $0 source destination
";
}

my $source = $ARGV[0];
my $destination = $ARGV[1];

if (-d $destination) {
    my $basename = basename($source);
    $destination = "$destination/$basename";
}

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

上述代码首先检查命令行参数是否为两个,如果不是则输出使用说明并终止程序。然后判断目标是否为目录,如果是,则获取源文件的基本名称,并将其添加到目标目录路径后。最后使用

rename

函数进行文件重命名或移动操作,若操作失败则输出错误信息。

85、编写一个程序,根据命令行参数的第一个参数是否为 -s 来决定为源文件创建符号链接还是硬链接到目标文件,如果目标是一个目录,则在该目录下创建链接。

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


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

# 检查命令行参数数量
if (@ARGV < 2) {
    die "Usage: $0 [-s] source target
";
}

my $is_symbolic = 0;
my $source;
my $target;

# 检查第一个参数是否为 -s
if ($ARGV[0] eq '-s') {
    $is_symbolic = 1;
    shift @ARGV;
}

# 获取源文件和目标文件
$source = $ARGV[0];
$target = $ARGV[1];

# 检查源文件是否存在
if (! -e $source) {
    die "Source file $source does not exist.
";
}

# 如果目标是目录,在目录下创建链接
if (-d $target) {
    my $basename = (split('/', $source))[-1];
    $target = $target . '/' . $basename;
}

# 创建链接
if ($is_symbolic) {
    if (symlink($source, $target)) {
        print "Symbolic link created from $source to $target.
";
    } else {
        die "Failed to create symbolic link: $!
";
    }
} else {
    if (link($source, $target)) {
        print "Hard link created from $source to $target.
";
    } else {
        die "Failed to create hard link: $!
";
    }
}

将上述代码保存为一个

.pl

文件,例如

create_link.pl

,然后在命令行中运行:

创建硬链接:

perl create_link.pl source_file target_file


perl create_link.pl source_file target_directory

创建符号链接:

perl create_link.pl -s source_file target_file


perl create_link.pl -s source_file target_directory

86、编写一个程序,从标准输入读取一系列数字,将它们排序后以 20 个字符宽度右对齐的格式输出。

以下是使用 Python 实现的程序示例:


numbers = []
while True:
    try:
        line = input()
        if not line:
            break
        num = float(line)
        numbers.append(num)
    except EOFError:
        break
    except ValueError:
        print("输入不是有效的数字,请重新输入。")
numbers.sort()
for num in numbers:
    print(f'{num:>20}')

该程序首先创建一个空列表用于存储输入的数字,通过循环不断从标准输入读取内容,将其转换为浮点数并添加到列表中。输入为空时停止读取,然后对列表中的数字进行排序,最后使用格式化字符串以 20 个字符宽度右对齐的格式输出每个数字。

87、编写程序,让用户输入一个字符串和一个子字符串,找出子字符串在字符串中出现的所有位置并输出。

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


string = input("请输入字符串:")
sub_string = input("请输入子字符串:")
positions = []
index = 0
while True:
    index = string.find(sub_string, index)
    if index == -1:
        break
    positions.append(index)
    index += 1
if positions:
    print(f"子字符串在字符串中出现的位置是:{positions}")
else:
    print("子字符串未在字符串中出现。")

这段代码首先让用户输入字符串和子字符串,然后使用

find

方法查找子字符串在字符串中出现的位置,并将位置存储在

positions

列表中,最后输出结果。

88、编写代码,将当前工作目录更改为根目录,然后执行 ls -l 命令。

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


use Cwd;
# 更改当前工作目录到根目录
chdir('/') or die "无法更改到根目录: $!";
# 执行 ls -l 命令
my $output = `ls -l`;
print $output;

这段代码首先使用

chdir

函数将当前工作目录更改为根目录,若更改失败则输出错误信息。然后使用反引号执行

ls -l

命令,并将结果存储在变量

$output

中,最后打印该结果。

89、编写代码将当前工作目录更改为根目录并执行 ls -l 命令

在 Perl 中可以这样实现:


use Cwd;
chdir('/') or die "无法更改到根目录: $!";
my $output = `ls -l`;
print $output;

以上代码首先使用

chdir

函数将当前工作目录更改为根目录,若更改失败则输出错误信息。然后使用反引号执行

ls -l

命令并将结果存储在

$output

变量中,最后打印输出。

90、编写代码将标准输出和标准错误输出重定向到文件,然后更改目录并执行 ls -l 命令

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


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.out


ls.err

文件,接着切换到根目录,最后执行

ls -l

命令。若执行过程中出现错误,会输出相应的错误信息。

91、编写代码根据日期判断是该去玩还是去工作

以下是一个简单的 Python 代码示例,用于根据日期判断是该去玩还是去工作。通常,周一到周五是工作日,需要工作;周六和周日是休息日,可以去玩。


import datetime

# 获取当前日期
current_date = datetime.datetime.now().weekday()

# 判断是工作日还是休息日
if current_date < 5:
    print('今天是工作日,该去工作了。')
else:
    print('今天是休息日,去玩吧!')

这段代码使用

datetime

模块获取当前日期的星期几,然后根据星期几的值判断是工作日还是休息日,并输出相应的信息。

92、编写代码设置信号处理程序来捕获一些信号并进行相应处理

在 Perl 中,可以使用

$SIG

哈希来设置信号处理程序。以下是一个简单的示例代码,用于捕获

INT

(通常是用户按下 Ctrl+C 时发送的信号)和

TERM

信号并进行相应处理:


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

# 定义信号处理程序
$SIG{INT} = sub {
    print "捕获到 INT 信号,程序即将退出...
";
    exit;
};

$SIG{TERM} = sub {
    print "捕获到 TERM 信号,程序即将退出...
";
    exit;
};

print "程序正在运行,按 Ctrl+C 或发送 TERM 信号来退出...
";

while (1) {
    sleep(1);
}

在上述代码中,我们使用

$SIG{INT}


$SIG{TERM}

分别设置了

INT


TERM

信号的处理程序。当捕获到这些信号时,程序会打印相应的消息并退出。主程序使用一个无限循环来模拟程序的运行,每秒钟休眠一次。

93、编写代码从文件中读取文本,然后让用户输入模式,输出匹配的字符串

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


# 打开文件并读取内容
file_path = 'your_file.txt'
with open(file_path, 'r', encoding='utf-8') as file:
    text = file.read()

# 让用户输入模式
pattern = input('请输入要匹配的模式:')

# 查找匹配的字符串
import re
matches = re.findall(pattern, text)

# 输出匹配的字符串
if matches:
    print('匹配的字符串如下:')
    for match in matches:
        print(match)
else:
    print('未找到匹配的字符串。')

代码说明:


文件读取

:使用

open

函数打开指定文件,并读取文件内容。


用户输入

:使用

input

函数让用户输入要匹配的模式。


模式匹配

:使用

re.findall

函数查找文本中所有匹配模式的字符串。


输出结果

:如果找到匹配的字符串,则将其输出;否则,输出未找到匹配字符串的提示。

© 版权声明

相关文章

暂无评论

none
暂无评论...