什么是Perl核心?
当我使用“Perl核心”这个术语时,我指的是随perl
解释器一起提供的标准库模块(实际上是指分布)。我认为这是大多数人使用该术语时的含义。了解哪些模块包含在Perl核心中是有用的;它使开发者能够构建无需外部依赖的程序,这些依赖的开发者几乎无法控制。perldoc网站有一个方便的按字母顺序排列的核心模块列表,我通常首先查看那里,浏览哪些模块包含在核心中。问题是,这可能会出错。
哪些模块包含在Perl核心中?
你知道自2011年以来(版本5.14.0),HTTP::Tiny一直随Perl一起分发吗?它没有列在perldoc上(尽管这在下一个QA黑客马拉松中已被列为要修复的内容)。幸运的是,有一个更好的解决方案:corelist
程序。这是由Module::CoreList提供的。让我们看看Module::CoreList第一次随Perl发布的版本
$ corelist -a Module::CoreList
Data for 2015-06-01
Module::CoreList was first released with perl v5.8.9
v5.8.9 2.17
v5.9.2 1.99
v5.9.3 2.02
v5.9.4 2.08
v5.9.5 2.12
v5.10.0 2.13
...
我已经截断了输出并保留了关键细节。它显示Module::CoreList自Perl版本5.8.9以来一直被包含在内。我在家里运行Fedora 23,它附带Perl版本5.22.1。运行系统Perl的corelist
$ sudo corelist -a Module::CoreList
sudo: corelist: command not found
该程序不存在;Fedora团队出于某种原因没有包含它。不仅如此,像Time::Piece这样伟大的核心模块也没有包含在内!
如果你没有corelist
,但想查看应随你的Perl版本一起捆绑的分发列表,你可以阅读perldoc perlmodlib
。
我有哪些模块?
有时,我们并不是真正想知道哪些模块包含在Perl核心中,而是想知道:“我安装了哪些模块?”对于非核心模块,我使用perldoc。
perldoc
不会显示我们已拥有的核心模块,在缺少核心模块的情况下,Module::CoreList也无法提供帮助(其结果基于模块的内部列表,这些模块应该是存在的,而不是实际存在的文件)。我处理这个问题的一个简单方法是用以下脚本来搜索@INC
的内容;即perl
搜索模块的目录
#!/usr/bin/env perl
use 5.10.3;
use Path::Tiny 'path';
use Getopt::Long 'GetOptions';
GetOptions(
'dir=s' => \my $dirpath,
) or die "Unrecognized option\n";
die "--dir is required\n" unless $dirpath && -d $dirpath;
# append a slash if missing
$dirpath .= '/' unless substr($dirpath, -1) eq '/';
my $iter = path($dirpath)->iterator({recurse => 1});
while (my $path = $iter->()) {
next unless "$path" =~ qr/.pm$/;
# remove the parent dir and trailing .pm from filename
my $module = substr("$path", length($dirpath), length("$path")-length($dirpath)-3);
$module =~ s/\//::/g;
say $module;
}
我这样运行它
$ chmod 755 list_modules
$ /usr/bin/perl -e 'for(@INC){ system "./list_modules -d $_" }'
我使用绝对路径/usr/bin/perl
来确保我得到的是系统上的perl
,而不是我通过plenv管理的本地perl
。这种方法的一个缺点是它列出了每个模块(.pm
文件),而不是每个分发(如果你不熟悉这种区别,请参阅这个解释)。另一个问题是,当系统使用符号链接时,它会列出重复的模块。因此,需要使用文本编辑器来整理程序输出。
程序呢?为了搜索Perl程序,我准备了一份来自Perl 5.22源代码的Perl程序列表,称为perl522_programs
c2ph
corelist
cpan
enc2xs
encguess
h2ph
h2xs
instmodsh
json_pp
libnetcfg
perl
perl5.22.1
perlbug
perldoc
perlivp
perlthanks
piconv
pl2pm
pod2html
pod2man
pod2text
pod2usage
podchecker
podselect
prove
pstruct
ptar
ptardiff
ptargrep
shasum
splain
xsubpp
zipdetails
然后我使用以下脚本,称为find_binary
来检查程序
#!/usr/bin/perl
my $bin = shift or die "You must provide a binary name to search for\n";
for ( qw(/sbin /bin /usr/sbin /usr/bin) )
{
my $path = "$_/$bin";
print "$path\n" if -e $path;
}
我这样运行它
$ chmod 755 find_binary
$ perl -ne 'chomp;system "./find_binary $_"' perl522_programs
这一行将在perl522_programs
文件中列出的每个程序上调用find_binary
脚本。我在搜索之前对行进行chomp
操作,以删除尾随换行符。这种方法并不完美;狡猾的Ubuntu附带了一个名为perldoc
的程序,但如果你运行它,系统会打印
You need to install the perl-doc package to use this program.
系统Perl中缺少的核心模块和程序
使用上述代码,我对比了Perl提供的模块和程序与以下系统提供的模块和程序。以下是缺失的内容
Fedora 23 | Ubuntu 14.04 LTS | OSX Yosemite 10.10.5 |
---|---|---|
B::Debug | CGI::Fast | GDBM_File |
Config::Perl::V | ODBM_File | |
CPANPLUS | perldoc | |
DB_File | ||
Devel::PPPort | ||
ExtUtils::Embed | ||
ExtUtils::MakeMaker::Locale | ||
ExtUtils::Miniperl | ||
File::Fetch | ||
File::Spec::VMS | ||
Filter::Simple | ||
IO::Compress::Adapter::Bzip2 | ||
IO::Uncompress::Adapter::Bunzip2 | ||
Math::BigFloat | ||
Math::BigInt | ||
Math::BigRat | ||
Math::Complex | ||
Math::Trig | ||
Module::Loaded | ||
PerlIO | ||
Text::Balanced | ||
Time::Piece | ||
Time::Seconds | ||
Unicode::Collate | ||
autodie | ||
bigint | ||
bignum | ||
bigrat | ||
experimental | ||
perlfaq | ||
corelist | ||
enc2xs | ||
libnetcfg |
Ubuntu和OSX预装了Perl 5.18,所以我查找了与5.18源代码不匹配的程序和模块。对于Fedora,我比较了系统perl
与5.22源代码。这些结果显示,Fedora缺少相当多的模块和程序:实验性、核心列表、autodie、Math::模块和Time::Piece似乎是重要的遗漏(它们由perl-core
包提供,必须单独安装)。对于Ubuntu,不包括perldoc
确实是一件遗憾的事。这是一个真正的遗憾。OSX的表现相当出色:几乎所有的核心模块和程序都存在。
结论
在编写使用核心Perl模块的程序时,请务必小心,尤其是如果您使用的是之前找到的任何模块或程序。一种解决方法是使用App::FatPacker将所有使用的模块编译成一个文件。另一种方法是使用pp创建编译后的二进制文件。最后,对于像Time::Piece这样的模块,您可以考虑将Perl的内置函数(如gmtime
和localtime
)包装在提供所需行为的子例程中,而不是使用该模块。
当然,使用本地安装的perl
比系统版本更容易。由perlbrew和plenv提供的本地Perls包含所有核心模块和实用程序。您也可以随时编译自己的Perl,这很容易。Strawberry Perl(Windows版本)甚至附带了一些有用的额外模块和C库。如果您确实必须依赖于系统Perl,您可能会发现根本不存在核心模块。
更新 感谢Grant McLean添加对Fedora包perl-core
的引用。2016-03-21
本文最初发布在PerlTricks.com上。
标签
反馈
这篇文章有什么问题吗?请通过在GitHub上打开问题或拉取请求来帮助我们。