先来一个例子吧
#!/usr/bin/perl
use warnings;
@array = qw(a b c d);
foreach (@array) {
print $_,”\n”;
例子的作用就是定义一个数组并把其中的元素打印出来,这里需要注意的是foreach循环部分,foreach循环的标准格式应该是:
foreach $element (@array){
}
其中数组@array将其中的元素依次赋值给$element,但是在上面那个程序中,我并没有这样做,在程序中,我就使用到了perl中内置的一个特殊变量
$_ 。
在程序第五行中:foreach (@array) 实际上就是等于 foreach $_
(@array),在这里,$_是默认是输入/输出,因此,如果在程序中有类似的没有明确声明的变量位置的时候,就有可能能使用$_代替。
perl -e “sleep(5);print qq(The PID of process perl.exe is :
$$)”;
这是一句命令行上使用的perl程序,作用就是打印出一段话:print qq(The PID of process perl.exe
is : $$) ,在这里,存在着特殊变量$$ ;
$$是当前perl解析器的进程ID(即,PID),大家可以将在段程序写在命令行上,该程序会在perl解析器运行5秒后打印出perl解析器的进程ID,大家可以在程序运行期间通过查看进程列表来确定打印结果是否正确(^_^不会错的)。
接下来是一个用来返回错误信息(或是错误号)的特殊变量
perl -e “opendir FH,’c:\none’ or die qq(can’t open:$!);”;
这句话就是要打开C盘下的一个none目录(而实际上我的C盘中并没有此目录,之所以这样写的目的就是为了引起一个程序中的错误信息),如果没有打开的话,会执行后面的die
qq(can’t open:$!)
can’t open:No such file or directory at -e line 1.
$!在open或是opendir中用的比较多(无论是打开文件还是管道或是其他)。
来个例子,说一个有意思的特殊内置变量
$text = “C:\\test.txt”;
open FH,$text or die “can’t open:$!”;
my $line = ;
close FH;
print $line;
print “#===========================#\n”;
undef $/;
open FH,$text or die “can’t open:$!”;
my $line = ;
close FH;
print $line;
=================================
C盘下的test.txt的内容是:
111111111111111111111111111
222222222222222222222222222
333333333333333333333333333
好,程序的运行结果是:
111111111111111111111111111
111111111111111111111111111
222222222222222222222222222
333333333333333333333333333
程序就不多废话了,作用就是读文件,关键部分在“$line =
”,尖括号操作符(即,<>)作用是读取一行文件内容(相信大多数教程或是书上都是这么写的),但是,这里所说的一行,实际上是有一个标准的,那就是当perl在遇到了换行符后,边认为是一行,而换行符默认情况下是由于$/这个特殊变量定义的,是缺省值。
也就是说,perl
在每次使用<>操作符读文件的时候,会先从$/中获得一个叫做“分隔符”的东西,并以该分隔符为标记来读取文件,如果按默认的$/来说,这个分割符就是一个换行符,所以,默认时,<>操作符才会每次读取一行文本。
在给出的例子中,有这样一句 :undef $/
,也就是将$/设置为未定义的值,这样一来呢,$/就不再起作用了,因此,大家可以看到,第二次进行同样的操作的时候,
<>操作符就不再是只读一行而是将文件内容全部读出来了。
接下来看一个会受到$/影响的内置变量,还是先说实例:
$text = “C:\\test.txt”;
open FH,$text or die “can’t open:$!”;
while () {
print “line $. is:$_”;
close FH;
先来看循环中的:print “line $. is:$_”
程序的作用是读文件,并且,将文件逐行赋值给$_(因为只用了<>操作符而没有指定内赋值变量,因此,默认就是赋值给了$_);
但是这里除了$_,还有一个变量“$.”
line 1 is:111111111111111111111111111
line 2 is:222222222222222222222222222
line 3 is:333333333333333333333333333
将上面的例子稍做修改,再看一下:
$text = “C:\\test.txt”;
undef $/; # 注意,多加了这一行
open FH,$text or die “can’t open:$!”;
while () {
print “line $. is:$_”;
close FH;
第二行多加了一句undef $/; ,上面已经说过它的作用了,来看一下这段程序运行的结果:
line 1 is:111111111111111111111111111
222222222222222222222222222
333333333333333333333333333
本来应该是三行的文本,不但被一次性打印出来,而且还指明了“line 1”(看来程序认为这个文本只有一行),为什么 ?
$text = “C:\\a.txt”;
open FH,$text or die “can’t open:$!”;
while () {
print “line $. is:$_\n”;
close FH;
再看一下C盘下的a.txt的内容:
ddd;bbb;ccc;fff;eee;
看一下运行结果:
line 1 is:ddd;
line 2 is:bbb;
line 3 is:ccc;
line 4 is:fff;
line 5 is:eee;
好,$.已经讲得差不多了,接下来再说一个它的特性,仍然是看程序说话:
$text = “C:\\test.txt”;
open FH,$text or die “can’t open:$!”;
while () {
print “line $. is:$_\n”;
print “\n”,$.;
close FH;
print “\n”,$.;
这个程序要注意的是最后三行中的两个print “\n”,$.;(一个是在关闭文件前,另外一个则是在关闭文件后)。
line 1 is:111111111111111111111111111
line 2 is:222222222222222222222222222
line 3 is:333333333333333333333333333
3
0
结果的前三行刚才就已经知道了,这不是我们关心的,我们应该关心的是最后两行结果(即两个print “\n”,$.;的结果);
$.变量是具有记忆性的(从原理上来将,它是一个包变量),因此,在关闭文件前打印会发现,它的值是还没有变化的(这时的值和最后一次读完文件的值均为3);
而在关闭文件后,该变量又被重新初始化为0了。
这个特性大家注意一下就可以了,因为其中的原理涉及到了perl的作用域和包的一些知识,不是很容易说清楚,所以就不说了,如果对包和作用域有了解的读者对这部分即使我不讲他们也应该能理解的。
再说最后一个吧
C:\>perl -e “print $^O;”;
MSWin32
注意,这里这个特殊变量$^O 最后一个字符是字母O,且大写。
如果是在linux下的话,结果就不是MSWin32了,而是Linux ;
perl的内置特殊变量还有很多的,例如常用的还有@_、@ARGV、$ARGV、%INC、%ENV等等,有很多,不可能一一列举了,这里给出一个比较有总结性的列表,是chinaunix上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 在导入模块时需要搜索的目录列表
$-[0]和$+[0] 代表当前匹配的正则表达式在被匹配的字符串中的起始和终止的位置
下面转自另一篇日志:
本文由 [color=red]chaoslawful[/color] 和鄙人共同翻译完成。
我原来翻译过一部分,不过没有翻完,后来幸亏 chaoslawful 的努力,所以才终于完成此文。
最新版本可以从这里获取(POD 格式):
http://svn.perlchina.org/trunk/POD2-CN/lib/POD2/CN/perlvar.pod
NAME
perlvar - Perl 预定义变量 DESCRIPTION 后面列出的名称对 Perl 来说具有特殊含义。
大多数标点名称都有合理的助记方法或类似于在 shell 中的用法。
然而,如果你就是想用长变量名,那只要在程序开头加上 use English; 即可。这样会为所有短名称在当前包中创建长名称别名。
其中一些甚至还有中间名,一般是从 awk 借用过来的。 一般来说,如果不需要
$PREMATCH,$MATCH 和 $POSTMATCH,那最好使用 use English '-no_match_vars'; 调用方式,因为它能避免在用正则表达式时出现效率降低的情况。见 English。 依赖当前被选中文件句柄的变量可以通过在 IO::Handle 但是这要比使用普通的内建变量效率低一些。(下面的概括行里包含的单词 HANDLE
即指 IO::Handle 对象。) 首先你要声明 use IO::Handle; 然后就可以用 method HANDLE EXPR 或者更安全的形式, HANDLE->method(EXPR) 每个方法都返回 IO::Handle 属性的旧值,同时接受一个可选的 EXPR。
如果提供了该参数,则其指定了所涉及 IO::Handle autoflush(),它会假定给定了参数 1,稍有不同。 载入 IO::Handle 量赋值, 就会引起一个运行时异常。 在修改本文档中描述的大部分特殊变量的缺省值时都需要特别小心。多数情况下应 在修改之前局部化这些变量,如果不这么做,就可能影响依赖于你所修改特殊变量
缺 省值的其他模块。下面是一次性读入整个文件的一种正确方法: open my $fh, "foo" or die $!;
local $/; # enable localized slurp mode
my $content = <$fh>;
close $fh; 但下面的代码就很糟糕: open my $fh, "foo" or die $!;
undef $/; # enable slurp mode
my $content = <$fh>;
close $fh; 因为一些模块可能想以默认的“行模式”从文件中读取数据,而一旦我们刚才
列出的代码得到执行,在同一个 Perl 解释器内运行的所有其他代码读到的 $/ 应该自己建立一个 "{}" 块,除非你已经处于某些小的 "{}" 块内。例如: my $content = '';
open my $fh, "foo" or die $!; local $/;
$content = <$fh>; close $fh; 下面是代码失控的一个例子: for (1..5){
nasty_break();
print "$_ "; sub nasty_break {
$_ = 5;
# do something with $_
} 你可能希望上述代码打印出: 1 2 3 4 5 但实际上得到的却是: 5 5 5 5 5 为什么?因为 nasty_break() 修改了 $_ 而没有事先将其局部化。
改正方法是增加 local(): local $_ = 5; 虽然在这样一个短小的例子里很容易发现问题,但在更复杂的代码中,如果不
对特殊变量进行局部化更改就是在自找麻烦。 下列内容按照先标量变量、后数组、最后散列的顺序排列。 $ARG
$_ 默认的输入和模式搜索空间。下面的几对代码都是等同的: while (<>) {...} # equivalent only in while!
while (defined($_ = <>)) {...} /^Subject:/
$_ =~ /^Subject:/ tr/a-z/A-Z/
$_ =~ tr/a-z/A-Z/ chomp
chomp($_) 以下是几处即使没有写明 Perl 也会假定使用 $_ 的地方: * 各种单目函数,包括像 ord() 和 int() 这样的函数以及除 "-t"
以外所有的文件 测试操作 ("-f","-d"),"-t" 默认操作 STDIN。 * 各种列表函数,例如 print() 和 unlink()。 * 没有使用 "=~" 运算符时的模式匹配操作 "m//"、"s///" 和
"tr///"。 * 在没有给出其他变量时是 "foreach" 循环的默认迭代变量。 * grep() 和 map() 函数的隐含迭代变量。 * 当 "while" 仅有唯一条件,且该条件是对 "<FH>"
操作的结果进行测试时,$_ 就是存放输入记录的默认位置。除了
"while" 测试条件之外不会发生这种情况。 (助记:下划线在特定操作中是可以省略的。) $a
$b 是使用 sort() 时的特殊包变量,参见 "sort" in perlfunc。
由于这一特殊性,$a 和 $b 即使在用了 "strict 'vars'"
指示符以后也不需要声明(用 use vars 或者 our())。 如果想要在
sort() 的比较块或者函数中使用它们,就不要用 "my $a" 或 "my $b"
将其词法化。 $<*digits*> 套 块中匹配的模式。(助记:类似 \digits。)
这些变量全都是只读的,对于 当前块来说具有动态作用域。 $MATCH
$& 含有上次成功的模式匹配所匹配到的字符串(不包括任何隐藏在块中的匹?
浠虻鼻?块所包围的 eval_r())。(助记:同一些编辑器中的 & 类似。) 降低。 参见 "BUGS"。 $PREMATCH 浠虻鼻?块所包围的 eval)。(助记:"`" 降低。 参见 "BUGS"。 $POSTMATCH 浠虻鼻?块所包围的 eval_r())。(助记:"'"
常常跟在引起的字符串之后。) 例如: local $_ = 'abcdefghi';
/def/;
print "$`:$&:$'\n"; # prints abc:def:ghi 该变量只读且对于当前块具有动态作用域。 在程序中任何地方使用该变量都会使所有正则表达式匹配产生可观的效率
降低。 参见 "BUGS"。 $LAST_PAREN_MATCH 式集中 到底哪一个匹配成功时,该变量是非常有用的。例如: /Version: (.*)|Revision: (.*)/ && ($rev = $+); (助记:积极一点儿向前看。)(译注:“积极”与“正号”是同一个单词?
? 该变量只读且相对于当前块具有动态作用域。 $^N 含有上一次成功搜索模式中最近闭合的组(即最右边的右括号构成的组)所 (译注:嵌套的单词为 Nest。) 该变量主要用在 "(?{...})" 为了有效地用一个变量($1、$2 等等之外的变量)捕获文本,可以将
"(...)" 替换为 (?:(...)(?{ $var = $^N })) 像这样设置并使用 $var 就能把你从计算括号个数的烦恼中解放出来了。 该变量对于当前块具有动态作用域。 @LAST_MATCH_END 。 $+[0]
为整个匹配在字符串中结束处的偏移量,这同用被匹配的变量调用 "pos"
函数得到的值一样。该数组的第 *n* 个元素保存了第 *n* 个子匹配
的偏移量,因此 $+[1] 就是紧接着 $1 结束处的偏移量,$+[2] 是
紧接着 $2 结束处的偏移量,以此类推。可以用 $#+ 0(或未定义值) 相当于告诉 Perl
可以假定字符串都是单行的,从而能进行模式匹配的优化。当 $* 为 0 理解的结果。它默认为未定义值。(助记:* 匹配很多东西。)
该变量只影响对 "^" 和 "$" 的解释。即使在 "$* == 0"
时也可以搜索一个字面的换行符。 在现在的 Perl 里不应使用 $*,在模式匹配中可以用 "/s" 和 "/m"
修饰符取代 它的功能。 对 $* 赋非数值量会触发一个警告(并使 $* 表现为 "$* == 0"),对 $*
赋数值量则会隐含对其应用 "int"。 HANDLE->input_line_number(EXPR)
$INPUT_LINE_NUMBER
$NR
$. 为最后访问的文件句柄对应的当前行号。 Perl 中每个文件句柄都记录从其中读出的行数。(Perl 当从某个文件句柄中读出一行(通过 readline() 或 "<>")或对其调用
tell() 或 seek() 时,$. 即成为那个句柄的行 计数器的别名。 你可以通过向 $. 赋值来调整计数器,但这并不会实际移动文件指针。 和文件句柄的别名关系。 关闭文件句柄时会复位 $.,但在没有 close()
就重新打开一个已打开的文件句柄 时不会这样。更多细节参见 "I/O
Operators" in perlop。"<>" 从不显式关闭文件,因此行号会在 ARGV
文件之间持续增长(不过请看看 "eof" in perlfunc 中的例子)。 你还可以用 "HANDLE->input_line_number(EXPR)" 行计数器,这样就无需担心最后访问的是哪个句柄了。 (助记:很多程序用“.”表示当前行号。) IO::Handle->input_record_separator(EXPR)
$INPUT_RECORD_SEPARATOR
$RS
$/ 为输入记录分隔符,默认为换行符。该变量会影响 Perl
对“行”这一概念 的理解。其功能类似于 awk 中的 RS 会将空白行作为终止标志。(空白行不能含有任何空格或制表符。) 设置为含有多个字符的字符串,以匹配多字符的终止标志;也可以设为
"undef" 以便一直读到文件结束。当文件含有连续的空白行时,把它设为
"\n\n" 和设为 "" 有少许不同:设为 ""
会把两个或更多连续的空白行视为单个 空白行;而设为 "\n\n" 这些字符是换行符也一样。(助记:在引用诗句时会用 /
作为行间的分隔。) local $/; # enable "slurp" mode
local $_ = <FH>; # whole file now here
s/\n[ \t]+/ /g; 切记:$/ 的内容是一个字符串,而不是正则表达式。awk 设为整数、存有整数的标量或可转换成整数的标量这些值的引用时,Perl 代码: local $/ = \32768; # or "32768", or \$var_containing_32768
open my $fh, $myfile or die $!;
local $_ = <$fh>; 会从 FILE 读取一条不长于 32768
字节的记录。如果你不是在读取一个面向记录 的文件(或者所用的 OS 整块的数据。若某条记录比你所设置的记录长度还大,就会把该记录拆成
若干片 返回。 在 VMS 上,记录读取是用 "sysread" 文件上混合使用记录和非记录读。(这不太可能成为问题,因为任何你想?
约锹寄J?读取的文件也许都不能在行模式下用。) 非 VMS 系统用普通
I/O 进行读取,因此 在一个文件中混合记录和非记录读是安全的。 参见 "Newlines" in perlport 以及 $.。 HANDLE->autoflush(EXPR)
$OUTPUT_AUTOFLUSH 道在每次 打印或写之后都会进行刷新。默认值为 0
(不管选中的通道实际上是否被系统所缓冲, $| 只是告诉你 Perl
是否在每次写完之后显式刷新)。典型情况下,若 STDOUT 接字输出 时很有用,比如你正在 rsh 下运行一个 Perl 输出内容。该变量不影响输入缓冲。关于输入缓冲请参见 "getc" in
perlfunc。 (助记:when you want your pipes to be piping hot.) IO::Handle->output_field_separator EXPR
$OUTPUT_FIELD_SEPARATOR
$OFS
$, 为 print 的输出域分隔符。通常 print
不经任何修饰就输出它的参数,要 得到更像 awk
的行为,可以将该变量设置成和 awk 的 OFS 变量一样
,以指定域之间打印什么。(助记:当 print
语句里有“,”时会打印的东西。) IO::Handle->output_record_separator EXPR
$OUTPUT_RECORD_SEPARATOR
$ORS
$\ 为 print 的输出记录分隔符。通常 print 任何结尾的换行符或其他表征记录结束的字符串。要得到更像 awk
的行为, 可以将该变量设为同 awk 的 ORS 变量一样,以指定在 print
的结尾输出 什么。(助记:设置 $\ 而不是在 print
结尾加“\n”。另外,它长得和 $/ 很像,但却是你从 Perl 单词“back”,还指代反斜杠“backslash”,起一语双关作用。) $LIST_SEPARATOR 类似,但应用于向双引号引起的字符串(或类似的内插字符串) ? $SUBSCRIPT_SEPARATOR
$SUBSEP
$; 为模拟多维数组时的下标分隔符。如果你这样引用一个散列元素 $foo{$a,$b,$c} 实际上意思就是 $foo{join($;, $a, $b, $c)} 但是别这么写 @foo{$a,$b,$c} # a slice--note the @ 它的意思是 ($foo{$a},$foo{$b},$foo{$c}) 默认为“\034”,同 awk 的 SUBSEP 就没法包含任何可靠的值了。
(助记:逗号(语法上的下标分隔符)是半个分号。是啊,我知道这完全没?