Perl-Perl模块2

岑光熙
2023-12-01

1. 使用简易模块

假设在程序里有个包含路径的长文件名,比如/usr/local/bin/perl,而你希望取出文件的基名(basename)而不包括目录。

my $name = "/usr/local/bin/perl";
(my $basename = $name) =~ s#.*##;

use v5.14;
my $name = "/usr/local/bin/perl";
my $basename = $name =~ s#.*##r;

这样写看起来好像不错,但实际上有安全隐患

  1. unix上的文件或目录名称可能会包含换行符,正则表达式中的点号(.)不能匹配换行符,可以加上/s修饰符来修正
  2. 这段代码只考虑的unix风格,没有考虑别的操作系统
  3. 不要重复造轮子

1. File::Basename模块

$ perldoc File::Basename # 查看使用说明
use File::Basename;

my $name = "/usr/local/bin/perl";
my $basename = basename $name; # 返回'perl'

这个模块会判断当前所用的操作系统,并且使用该系统默认的文件命名规则
File::Basename模块还提供了一些其它函数,比如dirname函数可以从文件全名中取得目录名称,还可以将文件名和扩展名分开,或者是改变默认的文件名规则

2. 仅选用模块中的部分函数

程序里现有的子程序名和模块里的某个函数同名
只需在File::Basename的use声明中加上导入列表来指明要导入的函数清单,就不会自动导入所有函数了

use File::Basename qw/ basename /;

像下面这样写的话说明我们完全不要引入任何函数

use File::Basename qw//;
use File::Basename();

这条指令告诉perl,加载File::Basename模块,但不要导入任何函数名称。导入函数的目的是要以简短的函数名使用,像basenamedirname。不过即使我们不导入这些名称,我们还是可以通过全名的方式来调用相应的函数

use File::Basename qw/ /; # 不导入函数名称

my $betty = &dirname($wilma); # 使用我们自己的子程序&dirname

my $name = "/usr/local/bin/perl";
my $dirname = File::Basename::dirname $name; # 使用模块中的dirname函数

模块里的dirname函数的全名是File::Basename::dirname。加载模块后,无论是否导入dirname这种简短名称,我们都可以随时使用函数全名的方式来调用

大多情况下,使用模块默认导入列表就可以了,大多数模块的默认导入列表里都会省略某些(不常使用的)函数

3. File::Spec模块

经常需要把基名和目录名合并形成新的文件全名

use File::Basename;

print "Please enter a filename: ";
chomp(my $old_name = <STDIN>);

my $dirname = dirname $old_name;
my $basename = basename $old_name;

$basename =~ s/^/not/; # 给基名加上前缀
my $new_name = "$dirname/$basename";

rename($old_name, $new_name)
	or warn "Can't rename '$old_name' to '$new_name': $!";

这段代码的问题在于,假设文件名遵循unix的惯例

可以利用File::Spec模块来操作文件说明(file specification),也就是文件名、目录名以及文件系统里的其它名称。它和File::Basename一样会在运行时判断操作系统的类型,并采用正确规则,但File::Spec是面向对象的(Object Oriented,OO)模块

use File::Spec;

print "Please enter a filename: ";
chomp(my $old_name = <STDIN>);

my $dirname = dirname $old_name;
my $basename = basename $old_name;

my $new_name = File::Spec -> catfile($dirname, $basename);

rename($old_name, $new_name) 
	or warn "Can't rename '$old_name' to '$new_name': $!";

调用方法时的全名应该由模块的名称(此处称为类(class))、一个瘦箭头(->)以及方法的简短名称构成。看到瘦箭头,就说明是面向对象的写法,后面是要调用的方法名

 类似资料: