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;
}
100、编写一个程序,提示用户输入一个目录名(默认为用户主目录),使用目录句柄列出该目录下的所有文件。
以下是一个满足需求的 Perl 程序示例:
use strict;
use warnings;
use File::HomeDir;
# 提示用户输入目录名,默认为用户主目录
print "请输入一个目录名(留空则使用用户主目录):";
my $dirname = <STDIN>;
chomp $dirname;
$dirname = File::HomeDir->my_home unless $dirname;
# 打开目录
opendir my $dh, $dirname or die "无法打开目录 $dirname: $!";
# 读取并列出目录下的所有文件
while (my $name = readdir $dh) {
next if $name =~ /^./; # 跳过隐藏文件
print $name, "
";
}
# 关闭目录
closedir $dh;
这个程序首先提示用户输入目录名,如果用户没有输入,则使用用户主目录。然后打开该目录,读取并列出所有非隐藏文件,最后关闭目录。
101、编写一个程序,删除命令行参数指定的所有文件,并在删除失败时给出警告。
以下是一个满足需求的 Perl 程序示例:
foreach my $file (@ARGV) {
if (!unlink($file)) {
warn "无法删除文件 $file: $!
";
}
}
上述程序会遍历命令行参数中的所有文件,尝试删除它们。若删除失败,会给出相应的警告信息。
102、编写一个程序,为命令行参数指定的源文件创建一个硬链接到目标文件,如果目标文件是一个目录,则将源文件的硬链接创建到该目录下。
以下是一个满足需求的 Perl 程序示例:
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec;
# 获取命令行参数
my ($source, $target) = @ARGV;
# 检查参数是否足够
if (!defined $source || !defined $target) {
die "Usage: $0 <source_file> <target_file_or_directory>
";
}
# 检查源文件是否存在
if (! -e $source) {
die "Source file $source does not exist.
";
}
# 检查目标是否为目录
if (-d $target) {
# 如果是目录,构建目标文件路径
my $filename = (File::Spec->splitpath($source))[2];
$target = File::Spec->catfile($target, $filename);
}
# 创建硬链接
if (link($source, $target)) {
print "Hard link created successfully from $source to $target.
";
} else {
die "Failed to create hard link: $!
";
}
将上述代码保存为一个
.pl
文件,例如
create_hard_link.pl
,然后在命令行中运行,如:
perl create_hard_link.pl source_file.txt target_directory
或者
perl create_hard_link.pl source_file.txt target_file.txt
103、编写一个程序,根据命令行参数的 -s 选项,为命令行参数指定的源文件创建一个符号链接或硬链接到目标文件,如果目标文件是一个目录,则将源文件的链接创建到该目录下。
以下是一个使用 Python 实现该功能的示例代码:
import os
import sys
is_symbolic = False
if '-s' in sys.argv:
is_symbolic = True
sys.argv.remove('-s')
if len(sys.argv) != 3:
print('用法: python script.py [-s] 源文件 目标文件')
sys.exit(1)
source_file = sys.argv[1]
target = sys.argv[2]
if os.path.isdir(target):
target = os.path.join(target, os.path.basename(source_file))
if is_symbolic:
try:
os.symlink(source_file, target)
print(f'符号链接创建成功: {target}')
except FileExistsError:
print(f'目标文件 {target} 已存在')
except PermissionError:
print(f'没有足够权限创建符号链接到 {target}')
except Exception as e:
print(f'创建符号链接时出错: {e}')
else:
try:
os.link(source_file, target)
print(f'硬链接创建成功: {target}')
except FileExistsError:
print(f'目标文件 {target} 已存在')
except PermissionError:
print(f'没有足够权限创建硬链接到 {target}')
except Exception as e:
print(f'创建硬链接时出错: {e}')
代码说明:
解析命令行参数
:检查
-s
选项是否存在,如果存在则将
is_symbolic
标志设置为
True
,并从参数列表中移除
-s
。
检查参数数量
:确保命令行参数包含源文件和目标文件。
处理目标目录
:如果目标是一个目录,则将源文件的名称添加到目标路径中。
创建链接
:根据
is_symbolic
标志创建符号链接或硬链接,并处理可能的异常。
104、编写一个程序,从标准输入读取一系列数字,将它们排序后以右对齐的格式输出。代码中使用了
push @numbers, split while <>;
这一行,解释其作用,并说明如果使用
%20s
代替
%20g
进行输出会有什么不同。
push @numbers, split while <>;
%20s
%20g
以下是实现该功能的程序:
my @numbers;
push @numbers, split while <>;
foreach (sort { $a <=> $b } @numbers) {
printf "%20g
", $_;
}
push @numbers, split while <>;
的作用是逐行读取标准输入,默认按空白字符分割每行内容为多个元素,再将这些元素添加到
@numbers
数组中。
如果使用
%20s
代替
%20g
进行输出:
%20s
是字符串格式,输出时字符串不会被改变,如
1.50
和
1.5
、
04
和
4
这些输入中的额外零字符会保留;
而
%20g
是数字格式,相等的数字在输出时会显示一致。
105、在对数字进行排序和打印的代码中,如果使用 %20s 而不是 %20g,会有什么不同?
下面是给定的【文本内容】:
%20s
是字符串格式,输出时字符串不会改变,像
1.50
、
04
中的额外零字符仍会保留;
%20g
是数字格式,相等的数字输出会相同。
106、如何先按姓氏、再按名字对哈希表 %last_name 的键进行排序并输出?
可以使用以下代码实现:
my @keys = sort {
"L$last_name{$a}" cmp "L$last_name{$b}" # by last name
or "L$a" cmp "L$b" # by first name
} keys %last_name;
foreach (@keys) {
print "$last_name{$_}, $_
";
}
107、如何使用
given
重写猜数字程序?
given
以下是使用
given
重写猜数字程序的示例代码:
use 5.010;
my $Verbose = $ENV{VERBOSE} // 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Verbose;
LOOP: {
print "Please enter a guess from 1 to 100: ";
chomp(my $guess = <STDIN>);
my $found_it = 0;
given( $guess ) {
when( ! /Ad+/ ) { say "Not a number!" }
when( $_ > $secret ) { say "Too High!" }
when( $_ < $secret ) { say "Too low!" }
default { say "Just right!";$found_it++ }
}
last LOOP if $found_it;
redo LOOP;
}
108、使用
given
重写数字猜谜程序(不一定使用智能匹配),该程序要求用户猜一个1到100之间的随机整数,根据用户输入给出相应提示,直到猜对为止。
given
以下是重写后的代码:
use 5.010;
my $Verbose = $ENV{VERBOSE} // 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Verbose;
LOOP: {
print "Please enter a guess from 1 to 100: ";
chomp(my $guess = <STDIN>);
my $found_it = 0;
given( $guess ) {
when( ! /Ad+/ ) { say "Not a number!" }
when( $_ > $secret ) { say "Too High!" }
when( $_ < $secret ) { say "Too low!" }
default { say "Just right!";$found_it++ }
}
last LOOP if $found_it;
redo LOOP;
}
109、编写一个程序,使用
given
语句打印从 1 到 105 的数字,若数字能被 3 整除则在其后追加 ‘Fizz’,能被 5 整除则追加 ‘Buzz’,能被 7 整除则追加 ‘Sausage’。
given
以下是实现该功能的 Perl 代码示例:
use feature 'given';
no warnings 'experimental::smartmatch';
for (1..105) {
given ($_) {
my $output = $_;
if ($_ % 3 == 0) {
$output .= ' Fizz';
}
if ($_ % 5 == 0) {
$output .= ' Buzz';
}
if ($_ % 7 == 0) {
$output .= ' Sausage';
}
print $output . "
";
}
}
这段代码使用
for
循环遍历 1 到 105 的数字,在
given
语句块中,根据数字能否被 3、5、7 整除来追加相应的字符串,并将结果打印输出。
110、编写一个程序,在 for 块中直接使用 when 来检查作为命令行参数传递的文件的存在性、可读性、可写性和可执行性。
以下是满足需求的 Perl 代码:
use 5.010;
for( @ARGV ) {
say "Processing $_";
when( ! -e ) { say "File does not exist!" }
when( -r _ ) { say "Readable!"; continue }
when( -w _ ) { say "Writable!"; continue }
when( -x _ ) { say "Executable!"; continue }
}
此程序会遍历命令行传入的所有文件,检查每个文件的存在性、可读性、可写性和可执行性,并输出相应结果。
111、编写一个使用
given
和智能匹配的程序,检查作为命令行参数传递的数字是否为质数。如果不是,则报告其除数。
given
以下是实现该功能的程序:
use 5.010;
# 定义一个子例程来返回一个数的除数列表
sub divisors {
my $number = shift;
my @divisors = ();
foreach my $divisor ( 2 .. ( $number/2 ) ) {
push @divisors, $divisor unless $number % $divisor;
}
return @divisors;
}
# 检查命令行参数
if (@ARGV != 1) {
die "请提供一个数字作为命令行参数。
";
}
# 获取命令行参数
my $number = $ARGV[0];
# 检查输入是否为数字
if ($number !~ /Ad+/) {
say "输入不是一个有效的数字!";
exit;
}
given ($number) {
my @divisors = divisors($number);
when (@divisors ~~ []) {
say "$number 是质数。";
}
default {
say "$number 的除数(除 1 和它本身)是:@divisors";
}
}
代码解释:
divisors
子例程
:该子例程接受一个数字作为参数,并返回该数字的所有除数(除 1 和该数字本身)的列表。
输入检查
:程序首先检查是否提供了一个命令行参数,如果没有则终止程序。然后检查输入是否为有效的数字,如果不是则输出错误信息并退出。
given
语句
:使用
given
语句对输入的数字进行处理。调用
divisors
子例程获取除数列表。如果除数列表为空,则表示该数字是质数,输出相应信息。否则,输出该数字的除数列表。
112、编写一个程序,报告一个数是偶数、奇数、能被一个喜欢的数字(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 ) { # $_ ~~ $favorite
say "$_ is my favorite number";
}
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 .. ($ARGV[0]/2 + 1) ) {
push @divisors, $divisor unless $number % $divisor;
}
return @divisors;
}
该程序通过
given - when
结构和智能匹配操作符
~~
来判断并报告数字的相关属性。
113、编写一个程序,将当前工作目录更改为根目录并执行 ‘ls -l’ 命令。
以下是实现该功能的程序:
chdir '/' or die "Can't chdir to root directory: $!";
exec 'ls', '-l' or die "Can't exec ls: $!";
第一行将当前工作目录更改为根目录,第二行使用多参数
exec
函数执行
'ls -l'
命令并将结果发送到标准输出。
114、编写一个程序,将标准输出(STDOUT)和标准错误输出(STDERR)分别重定向到文件 ‘ls.out’ 和 ‘ls.err’,将当前工作目录更改为根目录,并执行 ‘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: $!";
代码解释:
前两行将
STDOUT
和
STDERR
分别重定向到
'ls.out'
和
'ls.err'
文件。
第三行将当前工作目录更改为根目录。
最后一行执行
'ls -l'
命令。如果命令执行失败,会输出错误信息。
115、编写代码实现将当前工作目录更改为根目录并执行 ‘ls -l’ 命令
在Python中可以使用以下代码实现:
import os
# 更改当前工作目录为根目录
os.chdir('/')
# 执行 'ls -l' 命令
os.system('ls -l')
在Bash脚本中可以这样写:
#!/bin/bash
# 更改当前工作目录为根目录
cd /
# 执行 'ls -l' 命令
ls -l
116、编写代码实现将标准输出和标准错误输出重定向到文件,然后将当前工作目录更改为根目录并执行 ‘ls -l’ 命令,并思考相关错误信息的输出位置
以下是一个示例的Python代码来实现该功能:
import os
# 重定向标准输出和标准错误输出到文件
with open('ls.out', 'w') as stdout_file, open('ls.err', 'w') as stderr_file:
try:
# 更改当前工作目录到根目录
os.chdir('/')
# 执行 ls -l 命令
result = os.popen('ls -l 2>&1').read()
# 将标准输出写入文件
stdout_file.write(result)
except Exception as e:
# 将错误信息写入错误文件
stderr_file.write(str(e))
在上述代码中,使用
os.popen('ls -l 2>&1').read()
把标准错误输出重定向到标准输出,然后将所有输出写入
ls.out
文件。如果在更改目录或执行命令时发生异常,异常信息会被捕获并写入
ls.err
文件。
117、编写代码设置信号处理程序来捕获一些信号,并在另一个终端会话中发送信号进行测试
以下是一个示例,展示如何使用Python设置信号处理程序来捕获信号,并在另一个终端会话中发送信号进行测试。
编写代码设置信号处理程序(Python示例)
import signal
import time
# 定义信号处理函数
# 当接收到SIGINT(Ctrl + C)或SIGTERM信号时,会调用这个函数
# 它会打印一条消息并退出程序
def signal_handler(signum, frame):
print(f'接收到信号 {signum},程序即将退出。')
exit(0)
# 注册信号处理程序
# 将SIGINT(通常是Ctrl + C触发)和SIGTERM信号与信号处理函数绑定
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
print('程序正在运行,按Ctrl + C或发送SIGTERM信号来测试。')
while True:
time.sleep(1)
测试步骤
运行程序
:将上述代码保存为一个Python文件,例如
signal_test.py
,然后在终端中运行:
python signal_test.py
程序会开始运行并等待信号。
发送信号
:在另一个终端会话中,使用
ps
命令找到正在运行的Python程序的进程ID(PID)。例如:
ps -ef | grep signal_test.py
然后使用
kill
命令发送信号。
发送SIGTERM信号(这是正常的终止信号):
kill <PID>
这里的
<PID>
是你找到的Python程序的进程ID。
如果你想发送SIGINT信号,可以在运行程序的终端中按
Ctrl + C
。
注意事项
不同的操作系统和编程语言可能有不同的信号处理方式和信号编号。上述示例是基于Python和Unix/Linux系统的。
某些信号(如SIGKILL)是不能被捕获和处理的,因为它们是用来强制终止进程的。