perl内置函数
Perl提供了可以直接调用的、数目众多的函数。Perl Keywords(functions,syntax,variables,file-handles,Various),可以对以下对象进行操作:
数组: chomp, join, keys, map, pop, push, reverse, shift, sort, splice, split, unshift, values
数据库: dbmclose, dbmopen
目录: chdir, closedir, mkdir, opendir, readdir, rewinddir, rmdir, seekdir, telldir
文件: binmode, chdir, chmod, chown, chroot, close, eof, fnctl, fileno, flock, getc, glob, ioctl, link, lstat, open, print, printf, read, readdir, readlink, rename, rmdir, seek, select, stat, symlink, sysopen, sysread, syswrite, tell, truncate, umask, unlink, utime, write
(用户)组: endgrent, getgrent, getgrgid, getgrname, getpgrp, setgrent, setpgrp
哈希表: delete, each, exists, keys, values
主机: endhostent, gethostbyaddr, gethostbyname, sethostent
输入: getc, read, sysread
处理器间通讯: msgctl, msgget, msgrcv, msgsnd, pipe, semctl, semget, semop, shmctl, shmget, shmread, shmwrite
数学: abs, atan2, cos, exp, hex, int, log, oct, rand, sin, sqrt, srand
消息队列: msgctl, msgget, msgrcv, msgsnd
其他: bless, defined, do, eval, formline, import, ref, scalar, syscall, tie, tied, undef, untie, wantarray
网络: endnetent, getnetbyaddr, getnetbyname, getnetent, setnetent
输出: die, print, printf, syswrite, warn, write
口令: endpwent, getpwent, getpwname, getpwuid, setpwent
进程: alarm, die, dump, exec, exit, fork, getlogin, getpgrp, getppid, getpriority, kill, setpriority, sleep, system, times, umask, wait, waitpid
协议: endprotent, getprotobyname, getprotobynumber, getprotoent, getservbyname, getservbyport, getservent, setprotoent
正则表达式: grep, pos, quotemeta, reset, split, study
范围: caller, local, my
服务: endservent, getservbyname, getservbyport, getservent, setservent
套节字: accept, bind, connect, gethostbyaddr, gethostbyname, gethostent, getpeername, getservbyname, getservbyport, getservent, getsockname, getsockopt, listen, recv, select, send, setsockopt, shutdown, socket, socketpair
字符串: chop, chr, crypt, hex, index, join, lc, lcfirst, length, oct, ord, pack, q, qq, quotemeta, qw, qx, reverse, rindex, split, sprintf, substr, uc, ucfirst, unpack, vec 时间: gmtime, localtime, time
UNIX: chmod, chown, chroot, dump, endgrent, endhostent, endnetent, endprotent, endpwent, endservent, fnctl, fork,getgrent, getgrgid, getgrname, gethostent, getlogin, getnetent, getpgrp, getppid, getpriority, getprotobyname, getprotobynumber, getprotoent, getpwent, getpwname, getpwuid, getservbyname, getservbyport, getservent, ioctl, link, lstat, readlink, select, setgrent, sethostent, setnetent, setpgrp, setpriority, setprotoent, setpwent, setservent, sleep, syscall, times, umask, wait, waitpid
Perl builtin functions
Builtin functions are functions that Perl provides from the beginning. Explains how to call a function, pass arguments, and receive a return value. Please use it as a reference.
Math::BigInt和Math::BigFLoat
大数运算:扩展算数的精确度
use Math::BigInt;
$bi = Math::BigInt->new('11111111111111111111');
print $bi * $bi;
Math::Complex
复数运算
use Math::Complex;
$c1 = Math::Complex->new(-2,3);
$c2 = Math::Complex->new(4,5);
$c3 = $c1 * $c2;
print "($c1) X ($c2) = $c3\n";
Math::Trig
三角函数
integer(Pragmas)
转为整数计算
sin
调用语法 retval = sin(value);
参数为弧度值。
cos
调用语法 retval = cos(value);
参数为弧度值。
atan2
调用语法 retval = atan2(value1, value2);
运算并返回value1除以value2结果的arctan值,单位为弧度,范围在-PI~PI。
sqrt
调用语法 retval = sqrt(value);
平方根函数。value为非负数。
exp
调用语法 retval = exp(value);
返回e的value次方。
log
调用语法 retval = log(value);
以e为底的自然对数。
abs
调用语法 retval = abs(value);
绝对值函数。(Perl 4中没有)
rand
调用语法 retval = rand(num);
随机数函数,返回0和整数num之间的一个浮点数。
srand
调用语法 srand(value);
初始化随机数生成器。保证每次调用rand真正随机。
hex
16进制转换,将十六进制数(字符串形式)转化为十进制数。
print hex("10") . "\n";
print hex("0x10") . "\n";
print hex("ab") . "\n";
print hex("Ab") . "\n";
int
intnum = int(floatnum);
将浮点数舍去(截断)小数部分转化为整型数。
oct
decnum = oct(octnum);
将八进制数(字符串形式)或十六进制数("0x.."形式)转化为十进制数。
#示例:
从$value数字中剥离连续的16进制数字,从而将该数字转换为16进制数字
use integer;
my ($nval,@digits) = (258);
print "$nval in hex = ";
while($nval){
push @digits, (0 .. 9, 'a' .. 'f')[$nval & 15];
$nval /= 16;
}
while(@digits){
print pop @digits;
}
进程控制函数
sleep
sleep(time);
将程序暂停一段时间。time是停止的秒数。返回值为实际停止的秒数。
wait
procid = wait();
暂停程序执行,等待子进程终止。不需要参数,返回值为子进程ID,如果没有子进程,返回-1。
waitpid
waitpid(procid, waitflag);
暂停程序执行,等待特定的子进程终止。procid为等待的进程ID
其它控制函数
die
die(message);
终止程序并向STDERR输出错误信息。message可以为字符串或列表。如果最后一个参数不包含换行符,则程序文件名和行号也被输出。
warn
warn(message);
解说 与die类似,区别是不终止程序。
exit
exit(retcode);
终止程序并指定返回值。
kill
kill(signal, proclist);
给一组进程发送信号。
signal是发送的数字信号,9为杀掉进程。proclist是进程ID列表。详见kill的UNIX帮助。
caller
subinfo = caller();
返回调用者的程序名和行号,用于Debugger。
返回值为三元素的列表:
1.调用处的包名
2.调用者文件名
3.调用处的行号
chroot
chroot (dir);
改变程序的根目录,详见chroot帮助。
字符及字符串函数
chr
$char = chr(asciival);
字符码(ASCII)所对应的字符
foreach (65 .. 70) {
print chr(), " ";
}
ord
asciival = ord(char);
字符所对应的字符码(ASCII)
uc,lc,ucfirst,lcfirst
对段落字符串的大小写转换。
quotameta
newstring = quotemeta(oldstring);
将非单词的字母前面加上反斜线(\)。
语句:$string = quotemeta($string);
等效于:$string =~ s/(\W)/\\$1/g;
常用于模式匹配操作中,确保字符串中没有字符被看作匹配操作符。
join
调用语法 join(joinstr, list);
把字符串列表(数组)组合成一个长的字符串,在每两个列表元素间插入串joinstr。
sprintf
调用语法 sprintf(string, fields);
与printf类似,区别是结果不输出到文件,而作为返回值赋给变量。
$num = 26;
$outstr = sprintf("%d = %x hexadecimal or %o octal\n",$num, $num, $num);
print ($outstr);
结果输出 26 = 1a hexadecimal or 32 octal
chop
调用语法 $lastchar = chop(var);
var可为变量或数组,当var为变量时,最后一个字符被删除并赋给$lastchar,当var为数组/列表时,所有元素的最后一个字符被删除,最后一个元素的最后一个字母赋给$lastchar。
chomp
调用语法 result = chomp(var);
检查字符串或字符串列表中元素的最后一个字符是否为由系统变量$/定义的行分隔符,如果是就删除。返回值为实际删除的字符个数。
index
position = index(string, substring, position);
返回子串substring在字符串string中的位置,如果不存在则返回-1。参数position是可选项,表示匹配之前跳过的字符数,或者说从该位置开始匹配。
rindex
position = rindex(string, substring, position);
与index类似,区别是从右端匹配。
length
num = length(string);
返回字符串长度,或者说含有字符的数目。
pos
offset = pos(string);
返回最后一次模式匹配的位置。
substr
substr(expr, skipchars, length)
抽取字符串(或表达式生成的字符串)expr中的子串,跳过skipchars个字符,或者说从位置skipchars开始抽取子串(第一个字符位置为0),子串长度为length,此参数可忽略,意味着取剩下的全部字符。
当此函数出现在等式左边时,expr必须为变量或数组元素,此时其中部分子串被等式右边的值替换。
study
study(scalar);
用一种内部格式提高变量的访问速度,同一时刻只对一个变量起作用。
crypt
result = crypt(original, salt);
用DES算法加密字符串,original是将要加密的字符串,salt是两个字符的字符串,定义如何改变DES算法,以使更难解码。返回值为加密后的串。
---------------------------------------------------------------
perl语言中内置了大量的函数可供程序员使用
shift
$name1=shift(数组 @name)
该函数是将数组name最左边的标量变量移出数组,然后赋给name1.如果shift中没有参数就作用与@_(一个子过程用来接外部参数的数组)或者是@AVGN(脚本用来接命令行参数的数组)。
unshift
my num=unshft(@num, ())
将列表放在数组num的左边形成新数组num,返回num的元素个数。
sort
%num=sort key %num
按照num散列表中key的顺序排列该哈希表,返回排好的散列表。
split
split /模式/ 字符串
将字符串按照模式分割返回字符串数组。
exists
exists 散列键值
如果存在,返回true,否则返回false。
stat
@tmp=stat(文件描述符)
返回文件描述符对应的文件的属性的一个含有13个元素的数组。
keys
@tmp=keys(%hash)
$tmp=keys(%hash)
在list上下文中返回hash中的键值列表,然后赋值给tmp数组。
在sclar上下文中返回hash中的键值的总数量,然后赋值给tmp标量。
readline
$tmp=readline file
@tmp=readline file
在sclar上下文下读取file文件的一行数据,赋给tmp。
在list上下文下读取file文件的所有行数据,赋给tmp。
glob
@tmp=glob 正则表达式
返回满足正则表达式的文件列表,赋给tmp
defined
defined expr
正则表达式定义返回true,不然返回false
---------------------------------------------------------------
Perl的內置变量
让perl代码看起来更像perlish,而不是像C或者BASIC代码,最好的办法就是去了解perl的内置变量。perl可以通过这些内置变量可以控制程序运行时的诸多方面。来一起领略一下众多内置变量在文件的输入输出控制上的出色表现。
行计数
决定写这篇文章的一个原因就是,当我发现很多人都不知道“$.”内置变量的存在,这的确让人很吃惊,依然能看到很多人是这样写代码的:
my $line_no = 0;
while(){
++$line_no;
unless (/some regex/){
warn "Error in line $line_no ";
next;
}
# process the record in some way
}
由于某些原因,很多人似乎完全忽略了“$.”的存在,而这个变量的作用就是跟踪当前记录号。因此上面的代码也可以这样来写:
while(){
unless (/some regex/){
warn "Error in line $. ";
next;
}
# process the record in some way
}
译者注:通俗的说,这个内置变量就跟数据库中的记录指针非常相似,它的值就是你当前所读文件中的当前行号。虽然使用此内置变量并不能让你少打多少字,但重要的是我们可以省去一些不必要的变量声明。
另一种利用此内置变量的方法就是与连续操作符(..)一起使用。当用在列表上下文中时,(..)是列表构建操作符。它将从给出的开始和结束元素之间创建所有的元素。例如:
my @numbers = (1 .. 1000);
@numbers将包含从1到1000之间所有的整数。
但是当你在一个表达式上下文中使用此操作符时(比如,作为一个声明的条件),它的作用就完全不一样了。第一个操作数(“..”左侧的表达式)将被求值,如果得出的值为假,此次操作将什么也不做并返回假值。如果得出的值为真,操作返回真值并继续依次返回下面的值直到第二个操作数(“..”操作符右面的表达式)返回真值。举例子解释一下,假设你有一个文件,你只想处理这个文件的某几个部分。这几个部分以"!! START !!"为开始,"!! END !!"为结束。
使用连续操作符你可以这样写这段代码:
while(){
if (/!! START !!/ .. /!! END !!/){
# process line
}
}
每一次循环,连续操作符就会检查当前行。如果当前行与"/!! START !!/"不匹配,则操作符返回假值并继续循环。当循环到第一个与"/!! START !!/"相匹配的行时,连续操作符就会返回真值并执行if语句块中的代码。在while语句后面的循环中,连续操作符将再次检查"/!! END !!/"的匹配行,但是它直到找到匹配行后才会返回真值。这也就是说在"!! START !!" 和"!! END !!" 标记之间的所有行都将被处理。当找到"/!! END !!/"的匹配行后,连续操作符返回假并再次开始匹配第一个规则表达式。
这些与“$.”有什么关系呢?如果连续操作符的操作数有一个是常量的话,他们将被转化为整型数并于“$.”匹配。
因此输出一个文件的前10行内容我们可以这样写代码:
while(){
print if 1 .. 10;
}
关于“$.”最后要说明的一点是,一个程序中只有一个“$.”变量。如果你在从多个文件句柄中读数据,那么“$.”变量保存了最近读过的文件句柄中的当前记录号。如果你想要更复杂的解决此问题的方法那么你可以使用类似IO::FILE对象。这些对象都有一个input_line_number方法。
记录分隔符
“$/” 和 “$\”分别是输入输出记录分隔符。当你在读或者写数据时,他们主要控制用什么来定义一个“记录”。
详细地给大家解释一下吧。当你第一次学习perl,第一次知道文件输入操作符的时候,也许你会被告知“”就是从一个文件读入一行数据,而读入的每一行都包括一个新行字符(“\n”)。其实你所知道的这些并不完全是真的,那只是一个很特殊的情况。实际上文件输入操作符(“”)读数据后会包含一个在“$/”中指定的文件输入分隔符。让我们来看一个例子:
假设你有一个文本文件,内容是些有趣的引文或者一些歌词或者一些别的什么东西。比如类似下面的内容:
This is the definition of my life
%%
We are far too young and clever
%%
Stab a sorry heart
With your favorite finger
在这里有三段被一行“%%”分隔的引文。那么我们该如何从这个文件中一次读取一段引文呢。(译者注:这一段引文可是一行也可以是几行,比如例子中的第一段和第二段引文都是一行,而第三段引文是2行)。其中一个解决方法就是,一次从文件中读取一行,然后检查读入的行是否是“%%”。因此我们需要声明一个变量用来保存每次读入的数据,当遇到“%%”后重新组合先前读入的数据为一段完整的引文。哦,你还需要记得处理最后一段引文因为它最后没有“%%”。
这样的方法太过于复杂,一个简单的方法就是更改“$/”变量的内容。该变量的默认值是一个新行字符(“\n”),这也就是为什么“”操作符在读取文件内容时是一次读一行。但是我们可以修改这一变量内容为我们喜欢的任意值。比如:
$/ = "%% ";
while () {
chomp;
print;
}
现在我们每次调用“”,perl会从文件句柄中一次读取数据直到发现“%%\n”为止。(不是一次读一行了)。因此,当你用chomp函数来去掉读取数据的行分隔符时,就会删除“$/”变量中指定的分隔符了。在上例中经过chomp函数处理后的数据都会将%%\n”删除。
更改perl的特殊变量
在我们继续之前,我需要提醒你的是,当你修改了这些特殊变量的值后,你会得到一个警告。问题就是这些变量中的多数是被强制在主包中的。也就是说当你更改这些变量的值时,程序中用到这个值的地方(包括你包含的那些模块)都会给出警告。比如如果你在写一个模块,且你在模块中更改了“$/”变量的值,那么当别人把你的模块应用到自己的程序中时就必须相应的修改其他模块以适应程序的执行。所以修改特殊变量的值潜在地增加了查找bugs的难度。因此我们应该尽可能的避免它。第一个避免的方法是在你用完了修改后的特殊变量的值后应该将该特殊变量重值回原始值。比如:
$/ = "%% ";
while(){
chomp;
print;
}
$/ = " ";
而这个方法引发的另一个问题就是你不能确定在你重置特殊变量的值之前它的值就是系统默认值。(译者注:比如如果你在“$/ ="%%\n";”之前就修改过“$/”变量的值(不是默认值“\n”),那么最后重置回默认值肯定会引发错误的)。因此代码应该像如下才对,如下:
$old_input_rec_sep = $/;
$/ = "%% ";
while(){
chomp;
print;
}
$/ = $old_input_rec_sep;
上面的代码就避免了我们上述所说的bug,但是有另一个看起来更简练的方法。这个方法就是使用local来定义“$/”变量。如下:
{
local $/ = "%% ";
while(){
chomp;
print;
}
}
将代码以一对大括号括起来。一般的,代码块往往与循环,条件或者是子程序有关联,但是在perl中是可以单独用大括号来说明一个代码块的。而在这个代码块内用local定义的变量只在当前代码块中起作用。综上所述,不更改perl的内置变量是一个很好的习惯,除非它被本地化在一个代码块中。
“$/”的其他值
下面给出一些你可以赋予“$/”变量的特殊值,这些值可以开启一些有趣的行为。第一个就是设置该变量为未定义。这将开启slurp模式,开启该模式后我们可以一次性从一个文件中读取全部的文件内容。如下:
my $file = do { local $/; };
一个do语句块的返回值是语句块中最后一个表达式的值,如上面的do语句块的返回值就是“”操作符的返回值。而且由于“$/”变量被设置为undef(未定义),所以返回的就是整个文件的内容。需要注意的是,我们不需要明确地指定“$/”变量为undef,因为所有的perl变量在定义的时候就被自动初始化为undef。
设置“$/”变量为undef和空值是有很大区别的:设置成空值意味着开启paragraph模式(即段落模式),在这种模式下,每个记录就是一段以一个或更多空行为结束的文本段落。也许你会认为这种效果和把“$/”变量被设置为“\n\n”的效果是一样的,但是他们还是有微妙的区别的。如果一定进行比较,那么应该把“$/”变量设置成为“\n\n+”才能和paragraph模式相同。(注意,这里只是比方说。实际上是不能将“$/”变量设置为规则表达式的)“$/”变量的最后一个特殊值就是可以将其设置为一个整数标量变量的引用或者是一个整数常量的引用。
在这种情况下,从文件句柄中每次读出的数据最多是“$/”变量指定的大小。(在这里说“最多”是因为在文件的最后有可能剩余的数据大小小于“$/”变量指定的大小)。因此,如果想每次读出2kb的数据那么你可以这样做:
{
local $/ = 2048;
while(){
# $_ contains the next 2048 bytes from FILE
}
}
“$/” 和 “$.”
注意到当改变“$/”变量的值时候也相应的改变了perl对于记录的定义因此也改变了“$.”变量的行为。“$.”变量实际上保存的不再是当前“行”号了,而是当前的记录号。因此在前述的那个引文的例子中,“$.”变量将按照你所要读出数据的文件中的每一段引文递增。
关于“$\”
在前面的开始我提到了“$/”和“$\”变量作为输入和输出的记录分隔符。但是我们一直没有介绍“$\”变量。说实话,“$\”并不像“$/”那么有用。它包含了每次调用print输出时在最后要增加的字符串。它的默认值是空字符串,因此当你用print进行输出时,并没有任何东西跟在输出的数据后面。当然如果你非常希望能有个类似pascal的输出函数println,那么我们可以这样写:
use v5.20;
my @arr = (1, 'n', 3,'a','p');
println(@arr);
sub println{
local $\="\n";
print @_;
print "@_";
}
这样,在你每次用print输出数据时都会在数据后面增加一个"\n"(即换行符):
1n3ap
1 n 3 a p
其它 Print 变量
接下来的两个需要讨论的变量是非常容易混淆,尽管它们做的是完全不同的两件事。为了举例说明,看下面代码:
my @arr = (1, 2, 3);
print @arr;
print "@arr";
现在,如果不仔细地看你是否知道上面两个print调用的区别吗?
答案是,第一个print调用会紧挨着输出数组的三个元素,其间没有任何分割符(输出为:123)。然而第二个print语句输出的元素确实以空格为分隔的(输出为:1 2 3)。为什么会有此区别呢?
理解这个问题的关键就是,在每种情况下实际传给print调用的是什么。在第一种情况下,传递给print的是一个数组。perl将展开传递过来的数组为一个列表,列表中的三个元素被视为单独的参数。而第二种情况下,在传递给print之前,数组被双引号所包含。
确切地说第二种情况也可以理解成如下的过程:
my $string = "@arr";
print $string;
在第二种情况看来,传递给print函数的只是一个参数。事实上的结果就是对一个数组进行了双引号的包含,并不影响print函数是如何对待该字符串的。因此摆在面前的就是两种情况。当print接收一组参数的时候,它将紧凑地将这些参数输出而在输出的参数之间没有空格。当一个数组被双引号包含起来传递给print之前,数组的每个元素将以空格为分隔符展开为一个字符串。这两种情况是完全不相干的。不过从上面举的例子很容易看出人们是如何混淆这两种情况的。
当然如果愿意,perl允许我们改变这种行为。“$,”变量保存了分隔传递给print函数的参数所用到的字符串。正如上面介绍的,默认分割print参数的字符是空字符,当然这都是可以更改的:
my @arr = (1, 2, 3);{
local $, = ',';
print @arr;
}
这段代码将输出1,2,3
相应地,当一个数组被双引号包含传递给print函数时,展开这个数组后用来分割元素的字符则保存在“$"”变量中。代码如下:
my @arr = (1, 2, 3);{
local $" = '+';
print "@arr";
}
这段代码将输出 1+2+3
当然,在一个print语句的使用中“$"”变量并不是必须的。你可以用在任何被双引号包含的数组的地方。而且它也不仅仅是对数组才有效。也可以用在哈希表上。
my %hash = (one => 1, two => 2, three => 3);{
local $" = ' < ';
print "@hash{qw(one two three)}";
}
这将输出: 1 < 2 < 3
---------------------------------------------------------------
内置变量小结
在此大体了解了修改perl的内置变量的值可以给我们带来什么样的效果,如果还想了解地更深入一下,去阅读官方手册吧。
$-: 当前页可打印的行数,属于Perl格式系统的一部分
$!: 根据上下文内容返回错误号或者错误串
$": 列表分隔符
$#: 打印数字时默认的数字输出格式
$$: Perl解释器的进程ID
$%: 当前输出通道的当前页号
$&: 与上个格式匹配的字符串
$(: 当前进程的组ID
$): 当前进程的有效组ID
$*: 设置1表示处理多行格式.现在多以/s和/m修饰符取代之.
$,: 当前输出字段分隔符
$.: 上次阅读的文件的当前输入行号
$/: 当前输入记录分隔符,默认情况是新行
$:: 字符设置,此后的字符串将被分开,以填充连续的字段.
$;: 在仿真多维数组时使用的分隔符.
$?: 返回上一个外部命令的状态
$@: Perl解释器从eval语句返回的错误消息
$[: 数组中第一个元素的索引号
$\: 当前输出记录的分隔符
$]: Perl解释器的子版本号
$^: 当前通道最上面的页面输出格式名字
$^A: 打印前用于保存格式化数据的变量
$^D:调试标志的值
$^E:在非UNIX环境中的操作系统扩展错误信息
$^F:最大的文件捆述符数值
$^H:由编译器激活的语法检查状态
$^I:内置控制编辑器的值
$^L:发送到输出通道的走纸换页符
$^M:备用内存池的大小
$^O:操作系统名
$^P:指定当前调试值的内部变量
$^R:正则表达式块的上次求值结果
$^S:当前解释器状态
$^T:从新世纪开始算起,脚步本以秒计算的开始运行的时间
$^W:警告开关的当前值
$^X:Perl二进制可执行代码的名字
$_: 默认的输入/输出和格式匹配空间
$|: 控制对当前选择的输出文件句柄的缓冲
$~: 当前报告格式的名字
$`: 在上个格式匹配信息前的字符串
$’: 在上个格式匹配信息后的字符串
$+: 与上个正则表达式搜索格式匹配的最后一个括号
$<: 当前执行解释器的用户的真实ID
$ 含有与上个匹配正则表达式对应括号结果
$=: 当前页面可打印行的数目
$>: 当前进程的有效用户ID
$0: 包含正在执行的脚本的文件名
$ARGV:从默认的文件句柄中读取时的当前文件名
%ENV:环境变量列表
%INC:通过do或require包含的文件列表
%SIG:信号列表及其处理方式
@_: 传给子程序的参数列表
@ARGV:传给脚本的命令行参数列表
@INC:在导入模块时需要搜索的目录列表
---------------------------------------------------------------
用Perl内置的函数更改大小写
Perl提供了四个内置的函数类,从而能够轻松地改变字符和字的大小写。函数uc()会用大写返回其所有的参数,而lc()会用小写返回其参数。如果没有指定参数的话,uc()和lc()都会对$_变量进行操作。要改变字的首字母的大小写,就要使用ucfirst()和lcfirst()。和uc()以及lc()类似,如果没有指定参数,ucfirst()和lcfirst()会对$_变量进行操作。
这四个函数都不会改变其参数;它们只是会返回其参数的副本,而这个副本经过了改变。所以,你必须将结果分派给一个变量或者打印它,或者用其他的方式使用返回的值。像下面这样做是一个常见的错误:
$a = 'hello';
uc($a);
print $a;
第一眼看上去,你可能会预计这段代码将打印“HELLO”。但是,由于uc()没有更改其参数,所以它的结果只打印了小写的“hello”。要获得预期的结果,就要使用像下面这样的代码:
$a = 'hello';
$a = uc($a);
print $a;
更改字的大小写的另一种方式,是对双引号里面的字符串使用L和U逸出序列。使用下面的代码你可以获得与前面相同的结果:
$a = 'hello';
print "U$aE";
逸出字符E会结束前面逸出字符(在这里是U)开始的内容。
利用Perl内置的大写和小写函数,以及双引号里的逸出字符U和L,改变(字符的)大小写是很容易的。
---------------------------------------------------------------
字符串处理函数
index
调用语法:position=index(string,substring,position);
返回子串substring在字符串string中的位置,如果不存在则返回-1。参数position是可选项,表示匹配之前跳过的字符数,或者说从该位置开始匹配。
rindex
调用语法:position=rindex(string,substring,position);
与index类似,区别是从右端匹配。
perl中如果要查找一个字符子串在字符串中的位置,perl给我们提供了两个函数,一个为index,另外一个rindex。从两个函数上我们其实就可以看出,index为从前往后查找(从左到右),而rindex则是从后往前(从右到左)查找。下面我们就通过一个例子来看看index和rindex是如何工作的:
use v5.20;
my $string = "I can learn much form freeoa.net";
my $loc = index($string, "freeoa");
print "$loc\n";
$loc = index($string, "a");
print "$loc\n";
$loc = index($string, "Freeoa");
print "$loc\n";
$loc = rindex($string, "freeoa");
print "$loc\n";
上面这个程序的打印如下:
22
3
-1
22
从上面程序的打印结果我们也可以看出,如果index或rindex能够匹配到字符串,则会返回子字符串在整个字符串中的位置,注意此处的位置以0开始,如果在字符串中没有找到这个子串,则index或rindex返回-1。当然,如果能够判断出子串在字符串中的大概位置,可以给index或rindex指出开始搜索的起始位置,例如:
my $loc = index($string, "freeoa",20);
指定index从第20个编号的位置开始搜索freeoa这个字符串,这样可以大大的提高搜索的效率。
length
调用语法:num=length(string);
返回字符串长度,或者说含有字符的数目。
pos
调用语法:offset=pos(string);
返回最后一次模式匹配的位置。
substr
调用语法:substr(expr,skipchars,length)
抽取字符串(或表达式生成的字符串)expr中的子串,跳过skipchars个字符,或者说从位置skipchars开始抽取子串(第一个字符位置为0),子串长度为length,此参数可忽略,意味着取剩下的全部字符。当此函数出现在等式左边时,expr必须为变量或数组元素,此时其中部分子串被等式右边的值替换。
study
调用语法:study(scalar);
用一种内部格式提高变量的访问速度,同一时刻只对一个变量起作用。
lc/uc
调用语法:
retval=lc(string);
retval=uc(string);
将字符串全部转换成小/大写字母。
lcfirst/ucfirst
调用语法:
retval=lcfirst(string);
retval=ucfirst(string);
将首字母转换成小/大写。
quotameta
调用语法:newstring=quotemeta(oldstring);
将非单词的字母前面加上反斜线(\\)。
语句:string=quotemeta(string);
等效于:string=~s/(\\W)/\\\\1/g;
常用于模式匹配操作中,确保字符串中没有字符被看作匹配操作符。
use v5.20;
my $substring = 'quick.*?fox';
my $qs = quotemeta($substring);
say $qs;
结果输出:quick\.\*\?fox
join
调用语法join(joinstr,list);
把字符串列表(数组)组合成一个长的字符串,在每两个列表元素间插入串joinstr。
sprintf
调用语法sprintf(string,fields);
与printf类似,区别是结果不输出到文件,而作为返回值赋给变量。
use v5.20;
my $num=26;
my $outstr=sprintf("%d=%xhex-and-%ooctal",$num,$num,$num);
say($outstr);
结果输出:26=1ahex-and-32octal
---------------------------------------------------------------
数组: chomp, join, keys, map, pop, push, reverse, shift, sort, splice, split, unshift, values
数据库: dbmclose, dbmopen
目录: chdir, closedir, mkdir, opendir, readdir, rewinddir, rmdir, seekdir, telldir
文件: binmode, chdir, chmod, chown, chroot, close, eof, fnctl, fileno, flock, getc, glob, ioctl, link, lstat, open, print, printf, read, readdir, readlink, rename, rmdir, seek, select, stat, symlink, sysopen, sysread, syswrite, tell, truncate, umask, unlink, utime, write
(用户)组: endgrent, getgrent, getgrgid, getgrname, getpgrp, setgrent, setpgrp
哈希表: delete, each, exists, keys, values
主机: endhostent, gethostbyaddr, gethostbyname, sethostent
输入: getc, read, sysread
处理器间通讯: msgctl, msgget, msgrcv, msgsnd, pipe, semctl, semget, semop, shmctl, shmget, shmread, shmwrite
数学: abs, atan2, cos, exp, hex, int, log, oct, rand, sin, sqrt, srand
消息队列: msgctl, msgget, msgrcv, msgsnd
其他: bless, defined, do, eval, formline, import, ref, scalar, syscall, tie, tied, undef, untie, wantarray
网络: endnetent, getnetbyaddr, getnetbyname, getnetent, setnetent
输出: die, print, printf, syswrite, warn, write
口令: endpwent, getpwent, getpwname, getpwuid, setpwent
进程: alarm, die, dump, exec, exit, fork, getlogin, getpgrp, getppid, getpriority, kill, setpriority, sleep, system, times, umask, wait, waitpid
协议: endprotent, getprotobyname, getprotobynumber, getprotoent, getservbyname, getservbyport, getservent, setprotoent
正则表达式: grep, pos, quotemeta, reset, split, study
范围: caller, local, my
服务: endservent, getservbyname, getservbyport, getservent, setservent
套节字: accept, bind, connect, gethostbyaddr, gethostbyname, gethostent, getpeername, getservbyname, getservbyport, getservent, getsockname, getsockopt, listen, recv, select, send, setsockopt, shutdown, socket, socketpair
字符串: chop, chr, crypt, hex, index, join, lc, lcfirst, length, oct, ord, pack, q, qq, quotemeta, qw, qx, reverse, rindex, split, sprintf, substr, uc, ucfirst, unpack, vec 时间: gmtime, localtime, time
UNIX: chmod, chown, chroot, dump, endgrent, endhostent, endnetent, endprotent, endpwent, endservent, fnctl, fork,getgrent, getgrgid, getgrname, gethostent, getlogin, getnetent, getpgrp, getppid, getpriority, getprotobyname, getprotobynumber, getprotoent, getpwent, getpwname, getpwuid, getservbyname, getservbyport, getservent, ioctl, link, lstat, readlink, select, setgrent, sethostent, setnetent, setpgrp, setpriority, setprotoent, setpwent, setservent, sleep, syscall, times, umask, wait, waitpid
Perl builtin functions
Builtin functions are functions that Perl provides from the beginning. Explains how to call a function, pass arguments, and receive a return value. Please use it as a reference.
String
A function used to process strings.
| join | Concatenate strings by specifying a delimiter |
| length | Get the length of a string |
| substr | Cut and replace strings |
| index | Character search |
| rindex | Search for characters (from the end) |
| split | Split a string by specifying a delimiter |
| reverse | Reverse the strings |
| uc | Convert to uppercase |
| ucfirst | Convert first letter to uppercase |
| lc | Convert to lowercase |
| lcfirst | Convert first letter to lowercase |
| sprintf | Format string |
| chomp | Remove a line break |
| chr | Convert numbers to ASCII characters |
| ord | Convert ASCII characters to numbers |
| oct | Octal conversion |
| hex | Hexadecimal conversion |
| crypt | Create a digest and check your password |
Regular expression
Functions related to regular expression.
| quotemeta | Regular expression escape |
Array manipulation
A function for manipulating arrays.
| shift | Extract the beginning of an array element |
| unshift | Add element to the beginning of the array |
| pop | Extract the last element of the array |
| push | Add elements to the end of the array |
| plice | Detailed manipulation of array elements |
| grep | Extract elements that match the conditions |
| map | Map values |
| sort | sort |
| reverse | Reverse the order of the array |
Hash operation
A function for manipulating hashes.
| keys | Get a list of hash keys |
| values | Get a list of hash values |
| each | Fetch the hash key and value in order |
| exists | Confirmation of the existence of the hash key |
| delete | Delete hash key and value |
| reverse | Swap the hash key and value |
Subroutine
Functions related to subroutine.
| wantarray | Judgment of context |
| caller | Caller information |
| return | Returns a return value |
File input/output
Function used for file input/output.
| String output | |
| printf | Formatted string output |
| open | File open |
| close | File close |
| sysopen | Low level file open |
| getc | Get one character |
| binmode | Open mode change |
| flock | File lock |
| opendir | Directory open |
| closeddir | Directory closed |
| readdir | Read directory |
| read | Read from a file by specifying the number of bytes |
| sysread | Read from a file with a specified number of bytes (no buffering) |
| syswrite | Write to file by specifying the number of bytes (no buffering) |
Value definition
A function related to the definition of a value.
| undef | Get and set undefined values |
| defined | Check if the value is defined |
Context
| scalar function | Evaluate in scalar context |
File operation
Create/delete files/directories and other functions.
| unlink | Delete file |
| chdir | Change current directory |
| mkdir | Creating a directory |
| rmdir | Delete directory |
| chmod | Change permissions |
| stat | Get file information |
| fileno | Get file descriptor |
| glob | Get a list of files |
| umask | Mask settings |
| __LINE__ | Get line number |
| __FILE__ | Get file name |
| __DATA__ | Data section |
Date/Time
A function that manipulates date/time.
| time | Current time |
| localtime | Current time(with locale) |
| sleep | Sleep for a specified time |
Mathematical functions
Mathematical function.
| abs | Absolute value |
| sqrt | square root |
| int | Get the integer part |
| ceil | Round up the decimal point |
| floor | Decimal point devaluation |
| rand | Random value |
| looks_like_number | Numerical judgment |
| pi | pie |
| deg2rad | Angle conversion |
| sin | Ask for a sign |
| cos | Ask for cosine |
| exp | Exponential |
| log | Log function |
| srand | Reproducible random numbers |
See the following articles for the basics of handling numbers in Perl.
- Handling of numbers in Perl
Object Oriented
Functions related to object-oriented.
| bless | Object creation |
| __PACKAGE__ | Get the package name |
Exception handling
Function used in Exception handling.
| die | Exit the program |
| warn | Output warning |
| eval | Catch the exception |
Interprocess communication
Function used in interprocess communication.
| system | Run another process |
| fork | Fork |
| wait | Wait for child process |
| getpwuid | Get user ID |
| getpwnam | Get username |
| getgrnam | Get group name |
| kill | Kill the process |
Read configuration file
| do | Read the configuration file |
Binary processing
| pack | Pack the data in binary format |
| unpack | Restore packed data |
Math::BigInt和Math::BigFLoat
大数运算:扩展算数的精确度
use Math::BigInt;
$bi = Math::BigInt->new('11111111111111111111');
print $bi * $bi;
Math::Complex
复数运算
use Math::Complex;
$c1 = Math::Complex->new(-2,3);
$c2 = Math::Complex->new(4,5);
$c3 = $c1 * $c2;
print "($c1) X ($c2) = $c3\n";
Math::Trig
三角函数
integer(Pragmas)
转为整数计算
sin
调用语法 retval = sin(value);
参数为弧度值。
cos
调用语法 retval = cos(value);
参数为弧度值。
atan2
调用语法 retval = atan2(value1, value2);
运算并返回value1除以value2结果的arctan值,单位为弧度,范围在-PI~PI。
sqrt
调用语法 retval = sqrt(value);
平方根函数。value为非负数。
exp
调用语法 retval = exp(value);
返回e的value次方。
log
调用语法 retval = log(value);
以e为底的自然对数。
abs
调用语法 retval = abs(value);
绝对值函数。(Perl 4中没有)
rand
调用语法 retval = rand(num);
随机数函数,返回0和整数num之间的一个浮点数。
srand
调用语法 srand(value);
初始化随机数生成器。保证每次调用rand真正随机。
hex
16进制转换,将十六进制数(字符串形式)转化为十进制数。
print hex("10") . "\n";
print hex("0x10") . "\n";
print hex("ab") . "\n";
print hex("Ab") . "\n";
int
intnum = int(floatnum);
将浮点数舍去(截断)小数部分转化为整型数。
oct
decnum = oct(octnum);
将八进制数(字符串形式)或十六进制数("0x.."形式)转化为十进制数。
#示例:
从$value数字中剥离连续的16进制数字,从而将该数字转换为16进制数字
use integer;
my ($nval,@digits) = (258);
print "$nval in hex = ";
while($nval){
push @digits, (0 .. 9, 'a' .. 'f')[$nval & 15];
$nval /= 16;
}
while(@digits){
print pop @digits;
}
进程控制函数
sleep
sleep(time);
将程序暂停一段时间。time是停止的秒数。返回值为实际停止的秒数。
wait
procid = wait();
暂停程序执行,等待子进程终止。不需要参数,返回值为子进程ID,如果没有子进程,返回-1。
waitpid
waitpid(procid, waitflag);
暂停程序执行,等待特定的子进程终止。procid为等待的进程ID
其它控制函数
die
die(message);
终止程序并向STDERR输出错误信息。message可以为字符串或列表。如果最后一个参数不包含换行符,则程序文件名和行号也被输出。
warn
warn(message);
解说 与die类似,区别是不终止程序。
exit
exit(retcode);
终止程序并指定返回值。
kill
kill(signal, proclist);
给一组进程发送信号。
signal是发送的数字信号,9为杀掉进程。proclist是进程ID列表。详见kill的UNIX帮助。
caller
subinfo = caller();
返回调用者的程序名和行号,用于Debugger。
返回值为三元素的列表:
1.调用处的包名
2.调用者文件名
3.调用处的行号
chroot
chroot (dir);
改变程序的根目录,详见chroot帮助。
字符及字符串函数
chr
$char = chr(asciival);
字符码(ASCII)所对应的字符
foreach (65 .. 70) {
print chr(), " ";
}
ord
asciival = ord(char);
字符所对应的字符码(ASCII)
uc,lc,ucfirst,lcfirst
对段落字符串的大小写转换。
quotameta
newstring = quotemeta(oldstring);
将非单词的字母前面加上反斜线(\)。
语句:$string = quotemeta($string);
等效于:$string =~ s/(\W)/\\$1/g;
常用于模式匹配操作中,确保字符串中没有字符被看作匹配操作符。
join
调用语法 join(joinstr, list);
把字符串列表(数组)组合成一个长的字符串,在每两个列表元素间插入串joinstr。
sprintf
调用语法 sprintf(string, fields);
与printf类似,区别是结果不输出到文件,而作为返回值赋给变量。
$num = 26;
$outstr = sprintf("%d = %x hexadecimal or %o octal\n",$num, $num, $num);
print ($outstr);
结果输出 26 = 1a hexadecimal or 32 octal
chop
调用语法 $lastchar = chop(var);
var可为变量或数组,当var为变量时,最后一个字符被删除并赋给$lastchar,当var为数组/列表时,所有元素的最后一个字符被删除,最后一个元素的最后一个字母赋给$lastchar。
chomp
调用语法 result = chomp(var);
检查字符串或字符串列表中元素的最后一个字符是否为由系统变量$/定义的行分隔符,如果是就删除。返回值为实际删除的字符个数。
index
position = index(string, substring, position);
返回子串substring在字符串string中的位置,如果不存在则返回-1。参数position是可选项,表示匹配之前跳过的字符数,或者说从该位置开始匹配。
rindex
position = rindex(string, substring, position);
与index类似,区别是从右端匹配。
length
num = length(string);
返回字符串长度,或者说含有字符的数目。
pos
offset = pos(string);
返回最后一次模式匹配的位置。
substr
substr(expr, skipchars, length)
抽取字符串(或表达式生成的字符串)expr中的子串,跳过skipchars个字符,或者说从位置skipchars开始抽取子串(第一个字符位置为0),子串长度为length,此参数可忽略,意味着取剩下的全部字符。
当此函数出现在等式左边时,expr必须为变量或数组元素,此时其中部分子串被等式右边的值替换。
study
study(scalar);
用一种内部格式提高变量的访问速度,同一时刻只对一个变量起作用。
crypt
result = crypt(original, salt);
用DES算法加密字符串,original是将要加密的字符串,salt是两个字符的字符串,定义如何改变DES算法,以使更难解码。返回值为加密后的串。
---------------------------------------------------------------
perl语言中内置了大量的函数可供程序员使用
shift
$name1=shift(数组 @name)
该函数是将数组name最左边的标量变量移出数组,然后赋给name1.如果shift中没有参数就作用与@_(一个子过程用来接外部参数的数组)或者是@AVGN(脚本用来接命令行参数的数组)。
unshift
my num=unshft(@num, ())
将列表放在数组num的左边形成新数组num,返回num的元素个数。
sort
%num=sort key %num
按照num散列表中key的顺序排列该哈希表,返回排好的散列表。
split
split /模式/ 字符串
将字符串按照模式分割返回字符串数组。
exists
exists 散列键值
如果存在,返回true,否则返回false。
stat
@tmp=stat(文件描述符)
返回文件描述符对应的文件的属性的一个含有13个元素的数组。
keys
@tmp=keys(%hash)
$tmp=keys(%hash)
在list上下文中返回hash中的键值列表,然后赋值给tmp数组。
在sclar上下文中返回hash中的键值的总数量,然后赋值给tmp标量。
readline
$tmp=readline file
@tmp=readline file
在sclar上下文下读取file文件的一行数据,赋给tmp。
在list上下文下读取file文件的所有行数据,赋给tmp。
glob
@tmp=glob 正则表达式
返回满足正则表达式的文件列表,赋给tmp
defined
defined expr
正则表达式定义返回true,不然返回false
---------------------------------------------------------------
Perl的內置变量
让perl代码看起来更像perlish,而不是像C或者BASIC代码,最好的办法就是去了解perl的内置变量。perl可以通过这些内置变量可以控制程序运行时的诸多方面。来一起领略一下众多内置变量在文件的输入输出控制上的出色表现。
行计数
决定写这篇文章的一个原因就是,当我发现很多人都不知道“$.”内置变量的存在,这的确让人很吃惊,依然能看到很多人是这样写代码的:
my $line_no = 0;
while(){
++$line_no;
unless (/some regex/){
warn "Error in line $line_no ";
next;
}
# process the record in some way
}
由于某些原因,很多人似乎完全忽略了“$.”的存在,而这个变量的作用就是跟踪当前记录号。因此上面的代码也可以这样来写:
while(){
unless (/some regex/){
warn "Error in line $. ";
next;
}
# process the record in some way
}
译者注:通俗的说,这个内置变量就跟数据库中的记录指针非常相似,它的值就是你当前所读文件中的当前行号。虽然使用此内置变量并不能让你少打多少字,但重要的是我们可以省去一些不必要的变量声明。
另一种利用此内置变量的方法就是与连续操作符(..)一起使用。当用在列表上下文中时,(..)是列表构建操作符。它将从给出的开始和结束元素之间创建所有的元素。例如:
my @numbers = (1 .. 1000);
@numbers将包含从1到1000之间所有的整数。
但是当你在一个表达式上下文中使用此操作符时(比如,作为一个声明的条件),它的作用就完全不一样了。第一个操作数(“..”左侧的表达式)将被求值,如果得出的值为假,此次操作将什么也不做并返回假值。如果得出的值为真,操作返回真值并继续依次返回下面的值直到第二个操作数(“..”操作符右面的表达式)返回真值。举例子解释一下,假设你有一个文件,你只想处理这个文件的某几个部分。这几个部分以"!! START !!"为开始,"!! END !!"为结束。
使用连续操作符你可以这样写这段代码:
while(){
if (/!! START !!/ .. /!! END !!/){
# process line
}
}
每一次循环,连续操作符就会检查当前行。如果当前行与"/!! START !!/"不匹配,则操作符返回假值并继续循环。当循环到第一个与"/!! START !!/"相匹配的行时,连续操作符就会返回真值并执行if语句块中的代码。在while语句后面的循环中,连续操作符将再次检查"/!! END !!/"的匹配行,但是它直到找到匹配行后才会返回真值。这也就是说在"!! START !!" 和"!! END !!" 标记之间的所有行都将被处理。当找到"/!! END !!/"的匹配行后,连续操作符返回假并再次开始匹配第一个规则表达式。
这些与“$.”有什么关系呢?如果连续操作符的操作数有一个是常量的话,他们将被转化为整型数并于“$.”匹配。
因此输出一个文件的前10行内容我们可以这样写代码:
while(){
print if 1 .. 10;
}
关于“$.”最后要说明的一点是,一个程序中只有一个“$.”变量。如果你在从多个文件句柄中读数据,那么“$.”变量保存了最近读过的文件句柄中的当前记录号。如果你想要更复杂的解决此问题的方法那么你可以使用类似IO::FILE对象。这些对象都有一个input_line_number方法。
记录分隔符
“$/” 和 “$\”分别是输入输出记录分隔符。当你在读或者写数据时,他们主要控制用什么来定义一个“记录”。
详细地给大家解释一下吧。当你第一次学习perl,第一次知道文件输入操作符的时候,也许你会被告知“”就是从一个文件读入一行数据,而读入的每一行都包括一个新行字符(“\n”)。其实你所知道的这些并不完全是真的,那只是一个很特殊的情况。实际上文件输入操作符(“”)读数据后会包含一个在“$/”中指定的文件输入分隔符。让我们来看一个例子:
假设你有一个文本文件,内容是些有趣的引文或者一些歌词或者一些别的什么东西。比如类似下面的内容:
This is the definition of my life
%%
We are far too young and clever
%%
Stab a sorry heart
With your favorite finger
在这里有三段被一行“%%”分隔的引文。那么我们该如何从这个文件中一次读取一段引文呢。(译者注:这一段引文可是一行也可以是几行,比如例子中的第一段和第二段引文都是一行,而第三段引文是2行)。其中一个解决方法就是,一次从文件中读取一行,然后检查读入的行是否是“%%”。因此我们需要声明一个变量用来保存每次读入的数据,当遇到“%%”后重新组合先前读入的数据为一段完整的引文。哦,你还需要记得处理最后一段引文因为它最后没有“%%”。
这样的方法太过于复杂,一个简单的方法就是更改“$/”变量的内容。该变量的默认值是一个新行字符(“\n”),这也就是为什么“”操作符在读取文件内容时是一次读一行。但是我们可以修改这一变量内容为我们喜欢的任意值。比如:
$/ = "%% ";
while () {
chomp;
print;
}
现在我们每次调用“”,perl会从文件句柄中一次读取数据直到发现“%%\n”为止。(不是一次读一行了)。因此,当你用chomp函数来去掉读取数据的行分隔符时,就会删除“$/”变量中指定的分隔符了。在上例中经过chomp函数处理后的数据都会将%%\n”删除。
更改perl的特殊变量
在我们继续之前,我需要提醒你的是,当你修改了这些特殊变量的值后,你会得到一个警告。问题就是这些变量中的多数是被强制在主包中的。也就是说当你更改这些变量的值时,程序中用到这个值的地方(包括你包含的那些模块)都会给出警告。比如如果你在写一个模块,且你在模块中更改了“$/”变量的值,那么当别人把你的模块应用到自己的程序中时就必须相应的修改其他模块以适应程序的执行。所以修改特殊变量的值潜在地增加了查找bugs的难度。因此我们应该尽可能的避免它。第一个避免的方法是在你用完了修改后的特殊变量的值后应该将该特殊变量重值回原始值。比如:
$/ = "%% ";
while(){
chomp;
print;
}
$/ = " ";
而这个方法引发的另一个问题就是你不能确定在你重置特殊变量的值之前它的值就是系统默认值。(译者注:比如如果你在“$/ ="%%\n";”之前就修改过“$/”变量的值(不是默认值“\n”),那么最后重置回默认值肯定会引发错误的)。因此代码应该像如下才对,如下:
$old_input_rec_sep = $/;
$/ = "%% ";
while(){
chomp;
print;
}
$/ = $old_input_rec_sep;
上面的代码就避免了我们上述所说的bug,但是有另一个看起来更简练的方法。这个方法就是使用local来定义“$/”变量。如下:
{
local $/ = "%% ";
while(){
chomp;
print;
}
}
将代码以一对大括号括起来。一般的,代码块往往与循环,条件或者是子程序有关联,但是在perl中是可以单独用大括号来说明一个代码块的。而在这个代码块内用local定义的变量只在当前代码块中起作用。综上所述,不更改perl的内置变量是一个很好的习惯,除非它被本地化在一个代码块中。
“$/”的其他值
下面给出一些你可以赋予“$/”变量的特殊值,这些值可以开启一些有趣的行为。第一个就是设置该变量为未定义。这将开启slurp模式,开启该模式后我们可以一次性从一个文件中读取全部的文件内容。如下:
my $file = do { local $/; };
一个do语句块的返回值是语句块中最后一个表达式的值,如上面的do语句块的返回值就是“”操作符的返回值。而且由于“$/”变量被设置为undef(未定义),所以返回的就是整个文件的内容。需要注意的是,我们不需要明确地指定“$/”变量为undef,因为所有的perl变量在定义的时候就被自动初始化为undef。
设置“$/”变量为undef和空值是有很大区别的:设置成空值意味着开启paragraph模式(即段落模式),在这种模式下,每个记录就是一段以一个或更多空行为结束的文本段落。也许你会认为这种效果和把“$/”变量被设置为“\n\n”的效果是一样的,但是他们还是有微妙的区别的。如果一定进行比较,那么应该把“$/”变量设置成为“\n\n+”才能和paragraph模式相同。(注意,这里只是比方说。实际上是不能将“$/”变量设置为规则表达式的)“$/”变量的最后一个特殊值就是可以将其设置为一个整数标量变量的引用或者是一个整数常量的引用。
在这种情况下,从文件句柄中每次读出的数据最多是“$/”变量指定的大小。(在这里说“最多”是因为在文件的最后有可能剩余的数据大小小于“$/”变量指定的大小)。因此,如果想每次读出2kb的数据那么你可以这样做:
{
local $/ = 2048;
while(){
# $_ contains the next 2048 bytes from FILE
}
}
“$/” 和 “$.”
注意到当改变“$/”变量的值时候也相应的改变了perl对于记录的定义因此也改变了“$.”变量的行为。“$.”变量实际上保存的不再是当前“行”号了,而是当前的记录号。因此在前述的那个引文的例子中,“$.”变量将按照你所要读出数据的文件中的每一段引文递增。
关于“$\”
在前面的开始我提到了“$/”和“$\”变量作为输入和输出的记录分隔符。但是我们一直没有介绍“$\”变量。说实话,“$\”并不像“$/”那么有用。它包含了每次调用print输出时在最后要增加的字符串。它的默认值是空字符串,因此当你用print进行输出时,并没有任何东西跟在输出的数据后面。当然如果你非常希望能有个类似pascal的输出函数println,那么我们可以这样写:
use v5.20;
my @arr = (1, 'n', 3,'a','p');
println(@arr);
sub println{
local $\="\n";
print @_;
print "@_";
}
这样,在你每次用print输出数据时都会在数据后面增加一个"\n"(即换行符):
1n3ap
1 n 3 a p
其它 Print 变量
接下来的两个需要讨论的变量是非常容易混淆,尽管它们做的是完全不同的两件事。为了举例说明,看下面代码:
my @arr = (1, 2, 3);
print @arr;
print "@arr";
现在,如果不仔细地看你是否知道上面两个print调用的区别吗?
答案是,第一个print调用会紧挨着输出数组的三个元素,其间没有任何分割符(输出为:123)。然而第二个print语句输出的元素确实以空格为分隔的(输出为:1 2 3)。为什么会有此区别呢?
理解这个问题的关键就是,在每种情况下实际传给print调用的是什么。在第一种情况下,传递给print的是一个数组。perl将展开传递过来的数组为一个列表,列表中的三个元素被视为单独的参数。而第二种情况下,在传递给print之前,数组被双引号所包含。
确切地说第二种情况也可以理解成如下的过程:
my $string = "@arr";
print $string;
在第二种情况看来,传递给print函数的只是一个参数。事实上的结果就是对一个数组进行了双引号的包含,并不影响print函数是如何对待该字符串的。因此摆在面前的就是两种情况。当print接收一组参数的时候,它将紧凑地将这些参数输出而在输出的参数之间没有空格。当一个数组被双引号包含起来传递给print之前,数组的每个元素将以空格为分隔符展开为一个字符串。这两种情况是完全不相干的。不过从上面举的例子很容易看出人们是如何混淆这两种情况的。
当然如果愿意,perl允许我们改变这种行为。“$,”变量保存了分隔传递给print函数的参数所用到的字符串。正如上面介绍的,默认分割print参数的字符是空字符,当然这都是可以更改的:
my @arr = (1, 2, 3);{
local $, = ',';
print @arr;
}
这段代码将输出1,2,3
相应地,当一个数组被双引号包含传递给print函数时,展开这个数组后用来分割元素的字符则保存在“$"”变量中。代码如下:
my @arr = (1, 2, 3);{
local $" = '+';
print "@arr";
}
这段代码将输出 1+2+3
当然,在一个print语句的使用中“$"”变量并不是必须的。你可以用在任何被双引号包含的数组的地方。而且它也不仅仅是对数组才有效。也可以用在哈希表上。
my %hash = (one => 1, two => 2, three => 3);{
local $" = ' < ';
print "@hash{qw(one two three)}";
}
这将输出: 1 < 2 < 3
---------------------------------------------------------------
内置变量小结
在此大体了解了修改perl的内置变量的值可以给我们带来什么样的效果,如果还想了解地更深入一下,去阅读官方手册吧。
$-: 当前页可打印的行数,属于Perl格式系统的一部分
$!: 根据上下文内容返回错误号或者错误串
$": 列表分隔符
$#: 打印数字时默认的数字输出格式
$$: Perl解释器的进程ID
$%: 当前输出通道的当前页号
$&: 与上个格式匹配的字符串
$(: 当前进程的组ID
$): 当前进程的有效组ID
$*: 设置1表示处理多行格式.现在多以/s和/m修饰符取代之.
$,: 当前输出字段分隔符
$.: 上次阅读的文件的当前输入行号
$/: 当前输入记录分隔符,默认情况是新行
$:: 字符设置,此后的字符串将被分开,以填充连续的字段.
$;: 在仿真多维数组时使用的分隔符.
$?: 返回上一个外部命令的状态
$@: Perl解释器从eval语句返回的错误消息
$[: 数组中第一个元素的索引号
$\: 当前输出记录的分隔符
$]: Perl解释器的子版本号
$^: 当前通道最上面的页面输出格式名字
$^A: 打印前用于保存格式化数据的变量
$^D:调试标志的值
$^E:在非UNIX环境中的操作系统扩展错误信息
$^F:最大的文件捆述符数值
$^H:由编译器激活的语法检查状态
$^I:内置控制编辑器的值
$^L:发送到输出通道的走纸换页符
$^M:备用内存池的大小
$^O:操作系统名
$^P:指定当前调试值的内部变量
$^R:正则表达式块的上次求值结果
$^S:当前解释器状态
$^T:从新世纪开始算起,脚步本以秒计算的开始运行的时间
$^W:警告开关的当前值
$^X:Perl二进制可执行代码的名字
$_: 默认的输入/输出和格式匹配空间
$|: 控制对当前选择的输出文件句柄的缓冲
$~: 当前报告格式的名字
$`: 在上个格式匹配信息前的字符串
$’: 在上个格式匹配信息后的字符串
$+: 与上个正则表达式搜索格式匹配的最后一个括号
$<: 当前执行解释器的用户的真实ID
$ 含有与上个匹配正则表达式对应括号结果
$=: 当前页面可打印行的数目
$>: 当前进程的有效用户ID
$0: 包含正在执行的脚本的文件名
$ARGV:从默认的文件句柄中读取时的当前文件名
%ENV:环境变量列表
%INC:通过do或require包含的文件列表
%SIG:信号列表及其处理方式
@_: 传给子程序的参数列表
@ARGV:传给脚本的命令行参数列表
@INC:在导入模块时需要搜索的目录列表
---------------------------------------------------------------
用Perl内置的函数更改大小写
Perl提供了四个内置的函数类,从而能够轻松地改变字符和字的大小写。函数uc()会用大写返回其所有的参数,而lc()会用小写返回其参数。如果没有指定参数的话,uc()和lc()都会对$_变量进行操作。要改变字的首字母的大小写,就要使用ucfirst()和lcfirst()。和uc()以及lc()类似,如果没有指定参数,ucfirst()和lcfirst()会对$_变量进行操作。
这四个函数都不会改变其参数;它们只是会返回其参数的副本,而这个副本经过了改变。所以,你必须将结果分派给一个变量或者打印它,或者用其他的方式使用返回的值。像下面这样做是一个常见的错误:
$a = 'hello';
uc($a);
print $a;
第一眼看上去,你可能会预计这段代码将打印“HELLO”。但是,由于uc()没有更改其参数,所以它的结果只打印了小写的“hello”。要获得预期的结果,就要使用像下面这样的代码:
$a = 'hello';
$a = uc($a);
print $a;
更改字的大小写的另一种方式,是对双引号里面的字符串使用L和U逸出序列。使用下面的代码你可以获得与前面相同的结果:
$a = 'hello';
print "U$aE";
逸出字符E会结束前面逸出字符(在这里是U)开始的内容。
利用Perl内置的大写和小写函数,以及双引号里的逸出字符U和L,改变(字符的)大小写是很容易的。
---------------------------------------------------------------
字符串处理函数
index
调用语法:position=index(string,substring,position);
返回子串substring在字符串string中的位置,如果不存在则返回-1。参数position是可选项,表示匹配之前跳过的字符数,或者说从该位置开始匹配。
rindex
调用语法:position=rindex(string,substring,position);
与index类似,区别是从右端匹配。
perl中如果要查找一个字符子串在字符串中的位置,perl给我们提供了两个函数,一个为index,另外一个rindex。从两个函数上我们其实就可以看出,index为从前往后查找(从左到右),而rindex则是从后往前(从右到左)查找。下面我们就通过一个例子来看看index和rindex是如何工作的:
use v5.20;
my $string = "I can learn much form freeoa.net";
my $loc = index($string, "freeoa");
print "$loc\n";
$loc = index($string, "a");
print "$loc\n";
$loc = index($string, "Freeoa");
print "$loc\n";
$loc = rindex($string, "freeoa");
print "$loc\n";
上面这个程序的打印如下:
22
3
-1
22
从上面程序的打印结果我们也可以看出,如果index或rindex能够匹配到字符串,则会返回子字符串在整个字符串中的位置,注意此处的位置以0开始,如果在字符串中没有找到这个子串,则index或rindex返回-1。当然,如果能够判断出子串在字符串中的大概位置,可以给index或rindex指出开始搜索的起始位置,例如:
my $loc = index($string, "freeoa",20);
指定index从第20个编号的位置开始搜索freeoa这个字符串,这样可以大大的提高搜索的效率。
length
调用语法:num=length(string);
返回字符串长度,或者说含有字符的数目。
pos
调用语法:offset=pos(string);
返回最后一次模式匹配的位置。
substr
调用语法:substr(expr,skipchars,length)
抽取字符串(或表达式生成的字符串)expr中的子串,跳过skipchars个字符,或者说从位置skipchars开始抽取子串(第一个字符位置为0),子串长度为length,此参数可忽略,意味着取剩下的全部字符。当此函数出现在等式左边时,expr必须为变量或数组元素,此时其中部分子串被等式右边的值替换。
study
调用语法:study(scalar);
用一种内部格式提高变量的访问速度,同一时刻只对一个变量起作用。
lc/uc
调用语法:
retval=lc(string);
retval=uc(string);
将字符串全部转换成小/大写字母。
lcfirst/ucfirst
调用语法:
retval=lcfirst(string);
retval=ucfirst(string);
将首字母转换成小/大写。
quotameta
调用语法:newstring=quotemeta(oldstring);
将非单词的字母前面加上反斜线(\\)。
语句:string=quotemeta(string);
等效于:string=~s/(\\W)/\\\\1/g;
常用于模式匹配操作中,确保字符串中没有字符被看作匹配操作符。
use v5.20;
my $substring = 'quick.*?fox';
my $qs = quotemeta($substring);
say $qs;
结果输出:quick\.\*\?fox
join
调用语法join(joinstr,list);
把字符串列表(数组)组合成一个长的字符串,在每两个列表元素间插入串joinstr。
sprintf
调用语法sprintf(string,fields);
与printf类似,区别是结果不输出到文件,而作为返回值赋给变量。
use v5.20;
my $num=26;
my $outstr=sprintf("%d=%xhex-and-%ooctal",$num,$num,$num);
say($outstr);
结果输出:26=1ahex-and-32octal
---------------------------------------------------------------