<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; Perl</title>
	<atom:link href="https://blog.gmem.cc/category/work/perl/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Fri, 17 Apr 2026 09:20:32 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>Perl知识集锦</title>
		<link>https://blog.gmem.cc/perl-faq</link>
		<comments>https://blog.gmem.cc/perl-faq#comments</comments>
		<pubDate>Mon, 06 Jul 2009 03:41:18 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">https://blog.gmem.cc/?p=12215</guid>
		<description><![CDATA[<p>语言 快速参考 [crayon-69e2ae95bfac9896586170/] 模块 [crayon-69e2ae95bfad1675444892/] 上下文 在Perl中，相同的表达式，出现不同的地方（上下文）时，具有完全不同的意义。上下文包括标量上下文、列表上下文，在标量上下文中，Perl表达式的期望结果是标量，否则是列表。例如下面这段代码： [crayon-69e2ae95bfad4247544389/] 表达式@users在列表上下文中，会产生数组元素的列表，在标量上下文中则返回元素个数：  [crayon-69e2ae95bfad6625041959/] 某个具体表达式在不同上下文中的返回值是什么，各有不同，例如： 表达式 标量上下文 列表上下文 reverse 先把列表元素连接在一起，然后得到一个逆序的字符串 逆序后的列表 sort undef 排序后的列表 @ 数组元素个数 <a class="read-more" href="https://blog.gmem.cc/perl-faq">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/perl-faq">Perl知识集锦</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">语言</span></div>
<div class="blog_h2"><span class="graybg">快速参考</span></div>
<pre class="crayon-plain-tag">#!/usr/bin/perl
# 启用严格模式
use strict;
# 启用内建的警告功能
use warnings FATAL =&gt; 'all';


#####   其它           #####

# 老地方变量 $_，自动根据上下文推导此变量指向谁
foreach (qw/Alex Meng Cai/){
    print $_;  # 自动打印当前元素
}
$_ = "Hello\n";
print;  # 自动打印老地方变量

# 读取一行标准输入
my $line = &lt;STDIN&gt;;

# 在不产生歧义的前提下，函数调用的括号是可选的
chomp $line;  # 去除尾部的换行符

#####   标量数据类型   #####

# 数字，在内部总是以双精度浮点数来表示
my $num = 94605;      # my关键字创建词法变量，其作用域为当前代码块
$num = 6.02;
$num = 6.02e23;
# 可以使用下划线作为千分隔符
$num = 94_605;
# 非十进制整数
$num = 0b101010;
$num = 0777;
$num = 0xFF;
# 数字支持的操作符包括 + - * / %
$num = 10 % 3;

# 字符串
# 单引号字符串，总是字面含义
my $str = 'Hello \n World';
print $str; # Hello \n World
# 双引号字符串，支持转义字符
my $name = 'Alex';
my multiline = "
支持多行字符串
";
# 支持变量内插
print "Hello $name ${name} \n"; # Hello Alex!
# 字符串支持的操作符：
# 字符串连接
my $hello = 'Hello ' . $name;
# 字符串重复，重复次数非整数则向下取整，重复次数为0则生成空串
my $hello3 = $hello x 3; # HelloHelloHello

# 字符串和数字的自动转换
print 5 . 5;            # 只要是.操作符，就都认为是字符串，输出55
print 5 * "5";          # 只要是算术操作符，就认为是整数，输出25
# 甚至是 "5哈哈" * 5 也可以得出25


#####   标量变量   #####
# 标量变量必须以 $ 开头
# 支持双目赋值操作符
$num += 1;
$num *= 1;
# 未经明确初始化的变量，其初值未undef，可以转换为数字0
while ($n &lt; 10) {
    print($n++)   # 12345678910
}
# 下面的函数用于判断一个变量是否被初始化
$isdefined = defined($n);

#####   控制结构   #####

# 裸块，可以用于控制变量作用域
{
    my i = 0;
}

# if分支
# 对于字符串来说，''和'0'的值为假
# 对于数字来说， 0的值为假
# 其它类型，先转换为数字或字符串再判断
# 支持取反操作符 !
if ($name eq 'Alex') {
    # 字符串比较操作符 eq ne lt gt le ge
}
elsif ($num == 0) {
    # 数字比较操作符 == != &lt; &gt; &lt;= &gt;=
}
else {}

# 后缀式条件修饰词
print "$n is zero" if $n == 0;

# unlese结构，当表达式不满足的时候执行
unless (0 == 1) {
    print "Of course!";
}
else {}

# until循环，直到表达式不满足时才退出循环
until (0 == 1) {
    print "天荒地老";
}

# while循环
my $count = 0;
while ($count &lt; 10) {
    $count++;
}

# foreach循环
foreach $user (qw/Alex Meng Cai/){
    print $user;
}

# for循环
# 使用嵌套循环时，可以用标签
LABEL: for (my $i = 0; $i &lt; 10; $i++) {
    # 下面三个关键字，后面的标签都是可选的
    last LABEL; # 中止循环，类似于其它语言的break
    next LABEL; # 进行下一轮迭代，类似于其它语言的continue
    redo LABEL; # 重新进行本轮迭代
}

#####   数组   #####

# 列表直接量，使用()包围
# 数组变量，使用@作为前导
@empty = ();
@nums = (1, 2, 3);
@nums = (1 .. 100); # 100个数字的列表
# $#nums表示获取数组nums的最后一个元素的索引值，即长度-1
$num_count = $#nums + 1;
# 字符串的列表
@users = ('Alex', 'Meng', 'Cai');
@users = qw(Alex Meng Cai);  # 等价于上面，空格分隔元素
# qw简写可以使用任何界定符
qw{};

# 列表式赋值：
($alex, $meng) = ('Alex', 'Meng');
# 互换两个元素的值
# 注意引用数组元素时需要标量前缀$
($nums[ 0 ], $nums[ 1 ]) = ($nums[ 1 ], $nums[ 0 ]);

# 将数组作为栈来操作
$num = pop @nums;
push @nums, 0;

# pop/push是在数组的尾部操作，shift/unshift则是在头部
@nums = (0, 1, 2);
shift @nums;
unshift @nums,0;
unshift @nums,-1;
print @nums;  # -1012

# 数组在字符串中的内插，元素之间自动加空格
print "\n@nums";  # -1 0 1 2

# 反转操作符，获得列表的逆序
@nums_r = reverse @nums;

# 排序操作符，以ASCII序排列
sort @nums_r;


#####   哈希   #####

%users = ('Alex', 30, 'Meng', 27);
# 胖箭头语法：
%users = (
    'Alex' =&gt; 30,
    'Meng' =&gt; 27
);

#CRUD操作
$users{'Alex'} = 32;
$users{'Meng'} = 28;
$users{'Cai'} = 3;
print $users{'Ya'};   # 获取不存在的键会得到undef
exists  $users{'Ya'}; # 判断指定的键是否存在
delete $users{'Ya'};  # 删除指定的键

# 哈希可以和列表相互转换，转换为列表是，键值都作为列表元素
# 但是转换后，键值对的顺序不能保证
@users = %users;
print scalar @users; # 6

# 获得键列表和值列表
my @keys = keys %users;
my @vals = values %users;

# each函数，每次调用，返回下一个键值对（的列表）类似于其它语言中的迭代器
while (($k, $v) = each %users) {
    printf "%s = %d\n", $k, $v;
}

# %ENV存放环境变量
printf "$ENV{PATH}\n"


#####   子程序   #####
use feature 'state';
sub add {
    # 参数存放在名为@_的数组中，注意$_[0]和老地方变量$_毫无关系
    $_[0] + $_[1];
    # 最后一个表达式的结果，作为子程序的返回值，你也可以使用 return 语句随时返回
}
# 调用子程序，使用&amp;表达式
$result = &amp;add(1, 2);
print $result;  # 3
# 对于已经知晓子程序定义的地方，可以省略&amp;
print add(1, 2); # 3
# 如果子程序和Perl内置函数同名，不得省略&amp;
sub chomp {print('chomp')};&amp;chomp();

sub counter {
    # 持久性局部变量，跨越多次子程序存在，但是作用域限定在子程序内部
    state $count = 0;
    $count++;
    print $count;
}
counter counter counter; # 123</pre>
<div class="blog_h2"><span class="graybg">模块</span></div>
<pre class="crayon-plain-tag"># 引入模块以使用
# 在编译阶段，遇到下面的语句后会自动查找相关的代码并加载到当前脚本中
# /usr/share/perl/5.18/File/Basename.pm
use File::Basename;

# 你可以仅仅导入模块中特定的函数
use File::Basename qw/basename/;

my $fname = '/usr/bin/perl';
# 调用导入的函数
print basename $fname; # perl

# 不导入任何函数
use File::Basename qw//;
# 但是你仍然可以用全限定名称调用之
File::Basename::basename($fname)</pre>
<div class="blog_h2"><span class="graybg">上下文</span></div>
<p>在Perl中，相同的表达式，出现不同的地方（上下文）时，具有完全不同的意义。上下文包括<span style="background-color: #c0c0c0;">标量上下文、列表上下文</span>，在标量上下文中，Perl表达式的期望结果是标量，否则是列表。例如下面这段代码：</p>
<pre class="crayon-plain-tag">### 产生列表的表达式  ###
# 列表上下文
@users = reverse qw/Alex Meng Cai/;
print "@users\n";  # Cai Meng Alex
# 标量上下文
$users = reverse qw/Alex Meng Cai/;
print "$users\n";  # iaCgneMxelA

### 产生标量的表达式  ###
@nums = 6*5;       # 获得单元素的列表，元素值30
@nums = undef;     # 获得单元素的列表，元素值undef
@nums = ();        # 这样才能获得空列表</pre>
<p>表达式@users在列表上下文中，会产生数组元素的列表，在标量上下文中则返回元素个数： </p>
<pre class="crayon-plain-tag">@users = reverse qw/Alex Meng Cai/;
print "@users\n";  # Cai Meng Alex
print 0 + @users;  # 3
$n = @users;       # n == 3</pre>
<p>某个具体表达式在不同上下文中的返回值是什么，各有不同，例如：</p>
<table class="full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">表达式</td>
<td style="text-align: center;">标量上下文</td>
<td style="text-align: center;">列表上下文</td>
</tr>
</thead>
<tbody>
<tr>
<td>reverse</td>
<td>先把列表元素连接在一起，然后得到一个逆序的字符串</td>
<td>逆序后的列表</td>
</tr>
<tr>
<td>sort</td>
<td>undef</td>
<td>排序后的列表</td>
</tr>
<tr>
<td>@</td>
<td>数组元素个数</td>
<td>数组对应的列表</td>
</tr>
</tbody>
</table>
<p>某些情况下，是列表上下文还是标量上下文，不是很显眼，例如下面都是列表上下文：</p>
<pre class="crayon-plain-tag">( $alex, $meng ) = something;
( $alex ) = something;</pre>
<p>函数scalar可以强制切换到标量上下文：</p>
<pre class="crayon-plain-tag">@nums = (1, 2, 3);
print @nums;        # 123
print scalar @nums; # 3</pre>
<p>&lt;STDIN&gt;在列表上下文中，读取文件中所有行，存入列表，直到EOF（在控制台可以Ctrl + D触发EOF）：</p>
<pre class="crayon-plain-tag">@lines = &lt;STDIN&gt;;</pre>
<div class="blog_h2"><span class="graybg">正则式</span></div>
<div class="blog_h3"><span class="graybg">查找</span></div>
<pre class="crayon-plain-tag">$url = 'http://blog.gmem.cc/perl-faq?q=正则式';
$_ = $url;

# 对老地方变量进行匹配
if (/^https?:\/\/.*$/) {
    print "Valid URL";
}
# /***/实际上是m/***/的简写为了避免对 / 转义，可以使用m{***}
# i 表示大小写无关的匹配
if (m{^HTTPS?://.*$}i) {
    print "Valid URL";
}
# s 可以让 . 匹配任何字符，包括换行符
# x 可以在模式中添加任何空白，以方便阅读
# m 表示多行模式，^$可以匹配字符串内的换行符
m{ ^HTTPS?://.*$ }xis;

# 绑定操作符 string =~ pattern。不使用绑定操作符时，针对老地方变量进行匹配
$_ =~ m{ ^HTTPS?://.*$ }x;

# 模式中可以内插变量
m{ ^($scheme)?://.*$ };

# 捕获
if (m{ ^(https?)://(.*)\?(.*)}ix){
    # 在作用域内部使用$1 ... 引用捕获到的分组
    printf "Scheme: $1, Host: $2, Query: $3";
    #  Host: blog.gmem.cc/perl-faq, Query: q=正则式
}
# 捕获，使用命名分组
if (m{ ^(?&lt;scheme&gt;https?)://(?&lt;host&gt;.*)\?(?&lt;query&gt;.*)}ix){
    # 在作用域内部使用$+{name} 引用捕获到的分组
    printf "Scheme: $+{scheme}, Host: $+{host}, Query: $+{query}";
}
# 自动特殊捕获
$&amp;; # 匹配到的子串
$`; # 匹配子串前面的部分
$'; # 匹配子串后面的部分

# 在列表上下文中 m/***/ 返回所有捕获到的子串的列表
($first, $second, $third) = 'ONE TWO THREE' =~ /(\S+) (\S+) (\S+)/;
print $first; # ONE</pre>
<div class="blog_h3"><span class="graybg">替换</span></div>
<p>使用Perl正则式替换，可以直接修改目标字符串的内容：</p>
<pre class="crayon-plain-tag">$str = "Hello Alex Hello Meng";
$_ = $str;
# s/// 用于替换，可将/换成其它符号例如#
# 标记g表示全局替换，ixs也可以使用
s/ (?&lt;=Hello\s)\w+ /World/xig;
print "$_\n"; # Hello World Hello World

# s/// 的返回值为布尔型，如果替换成功则返回真
# 替换的时候也可以使用 =~ 操作符
# 替换的时候也支持使用捕获
# \U$1表示把捕获到的第一个分组转换为大写
# \L$1表示转换为小写
if($str =~ s/ (?&lt;=Hello\s)(\w+) /\U$1/xig ){
    print "$str\n"; # Hello ALEX Hello MENG
}</pre>
<div class="blog_h3"><span class="graybg">相关函数</span></div>
<pre class="crayon-plain-tag"># 基于正则式分割字符串
@fields = split /separator/, $str;
# 拼接字符串
$str = join $glue, @fields;</pre>
<div class="blog_h2"><span class="graybg">输入输出</span></div>
<pre class="crayon-plain-tag"># 读取标准输入
$line = &lt;STDIN&gt;;
chomp $line;
# 循环读取标准输入
while (&lt;STDIN&gt;) {
    print "You entered: $_";
    $|++; # 刷出
}

# @ARGV为程序参数数组，程序启动时自动创建，但你随时可以修改它
@ARGV = qw{/home/alex/Lua/projects/openrestry/logs/error.log};
# 从程序参数指定的文件（可以指定多个文件）中逐行读取
while (&lt;&gt;) {  # 钻石操作符
    # 下面的两个函数调用没有指定参数，自动使用$_
    chomp;
    print;
}


# 写出标准输出
# 打印程序参数指定的文件
print &lt;&gt;;
# 支持C风格的Printf
# %s 字符串
# %g 自适应的数字输出
# %d 十进制整数输出
# %f 浮点数输出
# %10s 输出为字符串，长度10字符，右对齐左补空格
# %12.4f 输出为浮点数，保留4位小数
printf "%s %g %d", 'string', 6.12, 94605;

# 从 5.10开始，支持Perl 6的say函数，该函数类似于print，但是会自动在尾部添加\n
use 5.010;
say "Hello!";</pre>
<div class="blog_h3"><span class="graybg">文件句柄</span></div>
<p>文件句柄（Filehandle）代表Perl程序和外界之间的IO联系，它是一个名字。</p>
<p>预定义的文件句柄包括：</p>
<table class="full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 15%; text-align: center;">句柄</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>STDIN</td>
<td>标准输入流</td>
</tr>
<tr>
<td>STDOUT</td>
<td>标准输出流</td>
</tr>
<tr>
<td>STDERR</td>
<td>标准错误流</td>
</tr>
<tr>
<td>DATA</td>
<td> </td>
</tr>
<tr>
<td>ARGV</td>
<td> </td>
</tr>
<tr>
<td>ARGVOUT</td>
<td> </td>
</tr>
</tbody>
</table>
<p>你可以创建并使用自己的文件句柄：</p>
<pre class="crayon-plain-tag"># &lt; 表示仅仅用于输入（读取）
open CONFIG, '&lt;/etc/mysql/my.cnf';
# &gt; 表示仅仅用于输出（写入）
open PIDFILE, '&gt;/var/run/mysql.pid';
# &gt;&gt; 表示用于追加输出
open LOG, '&gt;&gt;/var/log/mysql.log';
# 这样写也可以
my $success = open LOG, '&gt;&gt;', '/var/log/mysql.log';
# 如果打开成功，则返回值为真
unless ($success) {
    # die用于终结程序，并返回非0 退出码
    # $!存放上一次函数调用的错误信息
    die "Failed to open file : $!";
    # warn可以输出警告信息
}


# 使用文件句柄
# 读取
while (&lt;CONFIG&gt;) {
    # 逐行读取
    print;
}
# 写入
print CONFIG "...";


# 改变默认文件句柄
select CONFIG;
# 这样，默认输出到CONFIG
print '...';

# 设置变量$|的值为1，则当前默认句柄的缓冲区立即flush
$| = 1;

# 不再使用时，你需要关闭文件句柄
close LOG;</pre>
<div class="blog_h2"><span class="graybg">文件测试</span></div>
<p>使用文件操作符，示例：</p>
<pre class="crayon-plain-tag">if(-e $filename){
    print("File $filename exists\n");
}else{
    print("File $filename does not exists\n");
}</pre>
<p>支持的文件操作符如下，所谓操作符都可以前缀<pre class="crayon-plain-tag">!</pre>来取反：</p>
<table class="full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 15%; text-align: center;">操作符</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>-r</td>
<td>测试文件是否可被Effective UID/GID读</td>
</tr>
<tr>
<td>-w</td>
<td>测试文件是否可被Effective UID/GID读</td>
</tr>
<tr>
<td>-x</td>
<td>测试文件是否可被Effective UID/GID执行</td>
</tr>
<tr>
<td>-o</td>
<td>测试文件的所有者是否为Effective UID</td>
</tr>
<tr>
<td>-R</td>
<td rowspan="4">
<p>类似上面四个</p>
<p>但是针对Real UID/GID</p>
</td>
</tr>
<tr>
<td>-W</td>
</tr>
<tr>
<td>-X</td>
</tr>
<tr>
<td>-O</td>
</tr>
<tr>
<td>-e</td>
<td>测试文件是否存在</td>
</tr>
<tr>
<td>-z</td>
<td>测试文件是否为空（0字节）</td>
</tr>
<tr>
<td>-s</td>
<td>测试文件是否非空</td>
</tr>
<tr>
<td>-f</td>
<td>是否为普通文件</td>
</tr>
<tr>
<td>-d</td>
<td>是否为目录</td>
</tr>
<tr>
<td>-l</td>
<td>是否为符号链接</td>
</tr>
<tr>
<td>-p</td>
<td>是否为命名管道</td>
</tr>
<tr>
<td>-S</td>
<td>是否为套接字</td>
</tr>
<tr>
<td>-b</td>
<td>是否为块特殊文件</td>
</tr>
<tr>
<td>-c</td>
<td>是否为字符特殊文件</td>
</tr>
<tr>
<td>-t</td>
<td>是否被TTY打开的文件句柄</td>
</tr>
<tr>
<td>-u</td>
<td>文件模式的setuid位是否设置</td>
</tr>
<tr>
<td>-g</td>
<td>文件模式的setgid位是否设置</td>
</tr>
<tr>
<td>-k</td>
<td>文件模式的sticky为是否设置</td>
</tr>
<tr>
<td>-T</td>
<td>是否为ASCII或UTF-8文本文件</td>
</tr>
<tr>
<td>-B</td>
<td>是否为二进制文件</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">目录操作</span></div>
<pre class="crayon-plain-tag"># 获取目录构成的数组，支持通配符
my @dirs = &lt;/usr/local/tomcat_refactoring_*&gt;;
foreach my $dir (@dirs) {
    # 可以调用Shell命令
    system "rm -rf $dir/logs";
    # 下面的函数用于创建新目录，由于umask的原因，默认只能创建0755
    my $omask = umask;
    # 设置umask，即默认权限
    umask 0;
    mkdir "$dir/logs", 0777;
    umask $oumask;

    # 修改文件模式
    chmod "$dir/logs", 777
     
    # 移除文件，可以指定多个文件
    # 除非指定perl -U，并且当前用户为超级用户，否则下面的函数不会删除目录
    unlink $file1, $file2
}</pre>
<div class="blog_h2"><span class="graybg">调用Shell</span></div>
<pre class="crayon-plain-tag"># 方式一，使用system函数，调用完毕后返回当前脚本
system("sh", "script.sh", "--arg" );
system("sh script.sh --arg");

# 方式二，使用exe函数，调用永远不会返回
exec '/bin/echo', 'Your arguments are: ', @ARGV;
exec "sort $outfile | uniq";

# 方式三，反引号操作符
`script.sh --arg`
# 等价的qx//
qx/script.sh --option/;</pre>
<div class="blog_h2"><span class="graybg">操控环境变量</span></div>
<pre class="crayon-plain-tag">$ENV{'LUA_PATH'} = '';
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
$path = $ENV{'PATH'};</pre>
<div class="blog_h1"><span class="graybg">IDE</span></div>
<div class="blog_h2"><span class="graybg">Intellij</span></div>
<p>安装Intellij插件Perl，然后安装下面的模块，以支持调试：</p>
<pre class="crayon-plain-tag">cpanm -i  Devel::Camelcadedb</pre>
<div class="blog_h1"><span class="graybg">安装</span></div>
<div class="blog_h2"><span class="graybg">从源码构建</span></div>
<pre class="crayon-plain-tag">wget http://www.cpan.org/src/5.0/perl-5.26.1.tar.gz
tar xzf perl-5.26.1.tar.gz &amp;&amp; rm perl-5.26.1.tar.gz
cd perl-5.26.1
./Configure -Dotherlibdirs=/home/alex/Perl/5.26/lib/perl5/site_perl/5.26.1 -Dprefix=/home/alex/Perl/5.26 -d

make -j8 &amp;&amp; make install 

cd /home/alex/Perl
mv perl-5.26.1 /home/alex/Perl/5.26/src

cd 5.26/bin
curl -L https://cpanmin.us/ -o cpanm
chmod +x cpanm </pre>
<div class="blog_h1"><span class="graybg">CPAN</span></div>
<div class="blog_h2"><span class="graybg">何为CPAN</span></div>
<p>字面意思是综合性Perl归档网络（Comprehensive Perl Archive Network），它是一个Perl模块的仓库。</p>
<p>有时候，也指<pre class="crayon-plain-tag">cpan</pre> 命令，它是由CPAN提供的，自1997年开始随Perl发布的包管理工具。</p>
<div class="blog_h2"><span class="graybg">常用命令</span></div>
<div class="blog_h3"><span class="graybg">cpanm</span></div>
<p>一个脚本工具，用于从CPAN下载、解包、构建、安装Perl模块。</p>
<p>常用子命令：</p>
<table class=" full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 25%; text-align: center;">子命令</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>-i, --install</td>
<td>默认子命令，安装Perl模块</td>
</tr>
<tr>
<td>-U,--uninstall</td>
<td>删除Perl模块</td>
</tr>
<tr>
<td>--self-upgrade</td>
<td>升级cpanm，等价于<pre class="crayon-plain-tag">cpanm App::cpanminus</pre> </td>
</tr>
<tr>
<td>--info</td>
<td>以<pre class="crayon-plain-tag">AUTHOR/Dist-Name-ver.tar.gz</pre> 格式显示发行版的信息</td>
</tr>
<tr>
<td>--installdeps</td>
<td>安装目标模块的依赖</td>
</tr>
<tr>
<td>--look</td>
<td>下载、解包，然后通过Shell打开目录</td>
</tr>
</tbody>
</table>
<p>常用选项，默认选项可以通过环境变量<pre class="crayon-plain-tag">PERL_CPANM_OPT</pre> 指定：</p>
<table class=" fixed-word-wrap full-width">
<thead>
<tr>
<td style="width: 25%; text-align: center;">选项</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>-f, --force</td>
<td>强制安装模块，即使测试失败</td>
</tr>
<tr>
<td>-n, --notest</td>
<td>跳过模块测试</td>
</tr>
<tr>
<td>--test-only</td>
<td>仅运行测试，不安装</td>
</tr>
<tr>
<td>-S, --sudo</td>
<td>切换到root进行安装</td>
</tr>
<tr>
<td>-v, --verbose</td>
<td>冗长模式，自动开启 --interactive</td>
</tr>
<tr>
<td>-q, --quiet</td>
<td>安静模式，比默认情况更少的输出</td>
</tr>
<tr>
<td>-l, --local-lib</td>
<td>设置一个安装路径前缀，此前缀必须和local::lib兼容，例如：<br />
<pre class="crayon-plain-tag">cpanm -i -l /usr Module::Load</pre>
</td>
</tr>
<tr>
<td>-L, --local-lib-contained</td>
<td>与-l类似，但是同时开启 --self-contained</td>
</tr>
<tr>
<td>--self-contained</td>
<td>检查依赖时，假设任何非核心模块都没有在系统上安装，如果你希望把应用程序的依赖一起分发到其它机器上，可以使用</td>
</tr>
<tr>
<td>--interactive</td>
<td>启用交互式的配置（例如Makefile.PL）</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">常见问题</span></div>
<div class="blog_h2"><span class="graybg">如何影响@INC的取值</span></div>
<p><pre class="crayon-plain-tag">@INC</pre> 这个特殊的数组，包含了可以从中<span style="background-color: #c0c0c0;">寻找并加载Perl模块的一系列目录</span>。该数组的值和一系列因素相关。</p>
<div class="blog_h3"><span class="graybg">默认值</span></div>
<p>@INC的默认值在Perl解释器被编译的时候确定，你可以使用命令获得此默认值：</p>
<pre class="crayon-plain-tag">env -i perl -V
#  输出片段：
#  Summary of my perl5 (revision 5 version 16 subversion 3) configuration:
#  ...
#  Built under linux
#  Compiled at Nov 20 2015 03:29:53
#  下面的内容就是@INC的默认值
#  @INC:
#    /usr/local/lib64/perl5
#    /usr/local/share/perl5
#    /usr/lib64/perl5/vendor_perl
#    /usr/share/perl5/vendor_perl
#    /usr/lib64/perl5
#    /usr/share/perl5
#    .</pre>
<p>注意结尾的点号，表示当前工作目录。当以<pre class="crayon-plain-tag">-T</pre> 运行Perl解释器时该目录被忽略。 </p>
<p>要改变此默认值，需要在编译时配置</p>
<pre class="crayon-plain-tag">./Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3</pre>
<div class="blog_h3"><span class="graybg">环境变量的影响</span></div>
<p>环境变量<pre class="crayon-plain-tag">PERL5LIB</pre> 或者<pre class="crayon-plain-tag">PERLLIB</pre> 会影响@INC的取值。如果PERL5LIB没有定义，才自动使用PERLLIB。</p>
<p>通过PERL5LIB你可以指定一系列分号分隔的目录，<span style="background-color: #c0c0c0;">这些目录会自动添加到默认值的前面（优先搜索）</span>。</p>
<div class="blog_h3"><span class="graybg">Perl命令行选项的影响 </span></div>
<p>使用<pre class="crayon-plain-tag">-I</pre> 选项，可以附加一系列分号分隔的目录到@INC的头部：</p>
<pre class="crayon-plain-tag">perl -I ~/perl5</pre>
<div class="blog_h3"><span class="graybg">lib指令的影响</span></div>
<p>你可以通过类似下面的代码，继续附加一系列分号分隔的目录到@INC的头部：</p>
<pre class="crayon-plain-tag">use lib ("/dir1", "/dir2");</pre>
<div class="blog_h3"><span class="graybg">作为数组来操控</span></div>
<p>你可以直接修改@INC，就像普通Perl数组一样。  </p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/perl-faq">Perl知识集锦</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/perl-faq/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
