Perl基础知识(备忘)
2013-12-03 15:08
323 查看
zz : http://blog.csdn.net/dongtingzhizi/article/details/13509079
前两天项目中遇到了一个Perl脚本程序,需要读懂该程序,由于以前重来没有用过Perl语言,所以没法搞定。今天抽空把该语言的基础看了一遍,基本上内读懂Perl脚本程序了吧。真是如网上很多分享的经验所说,第一:会一门语言后,学习其他的语言也就容易了,所有的语言包含的内容都差不多,只要熟悉一下该语言的语法就OK了;第二:会一门语言的有经验的开发者,跟本没有必要花大量的时间把一门新语言重头读到尾来学习他,看看基础就可以用了,用的过程中不明白的再去查阅手册或资料。
网上不少人说Perl语言受关注度越来越低,在服务器端慢慢的被PHP取代,但是作为系统脚本语言还是有他的特点的,我觉得最主要的是:强大的正则表达式和模式匹配功能,在sed和awk中也用到了类似的语法。
入门可以参考以下教程:
http://www.cbi.pku.edu.cn/chinese/documents/perl/index.htm
http://www.phpchina.com/resource/manual/perl/perl5-1.htm
下面是我学习中记下的一些基础知识,当作备忘吧。
● 连续数值的列表有缩写形式,例如:(1 .. 10),(1, 3, 5 .. 10);浮点型的(0.5 .. 3.8)表示(0.5, 1.5, 2.5, 3.5); 字符型的(a .. z)表示小写字母a到z。
● 数组变量以@开头,可以定义与简单变量相同的名字,$var和@var不冲突。
● 数组可以直接给普通变量赋值,例如:
@arr = (1 .. 3);
($a, $b) = @arr; #a为1, b为2
($c, $d, $e, $f) = @arr; #c为1, d为2, e为3, f为null
● qw函数创建字符串数组,不需要使用逗号和引号,例如:
@arr = qw(aaa bbb ccc ddd);
● 可以从标准输入读入数组,按CTRL+D结束输入,例如:
@arr = <STDIN>;
● 访问数组的某个元素,用$,数组下标从0开始,例如:
@arr = (1 .. 3);
$arr[0]; $arr[1]; $arr[2]; 分别访问数组第1、2、3个元素。
● 获取数组长度:$len = @arr;
● 数组截取(用@),(注意规则是:取多个数组元素用@,取单个数组元素用$。)例如:
@arr = (1 .. 6);
@sub1 = @arr[0, 2, 4]; #sub1为(1, 3, 5)
@sub2 = @arr[1, 3, 5]; #sub1为(2, 4, 6)
@sub1 = @arr[0, 3..5]; #sub1为(1, 4, 5, 6)
● 数组访问支持负数下标,例如:
@arr = (1, 2, 3);
$item = $arr[-1]; #item为3
$sub = @arr[0, -1]; #sub为(1,3)
(作用于数组的函数)
● chop和chomp函数可用于数组,例如:chomp(@arr)用于去掉arr中所有字符串尾部的换行符。
● push和pull操作数组相当于栈操作,数组的右边界为栈的顶部,即从右边“弹出”或者“压入”元素。
● sort用于对数组元素进行排序,调用形式为:@sorted = sort(@arr); 执行sort函数后原数组不会改变,所以要通过返回值接收排好序的数组。默认情况下,按所有元素的ASCII顺序排序(包括数字),所以不能简单调用sort函数对数值型元素排序。如果需要按数值大小进行排序,应该这样调用:
升序:@sorted = sort { $a <=> $b } @arr;
降序:@sorted = sort { $b <=> $a } @arr;
● reverse函数用于反转一个数组,例如:
@arr = (1 .. 6);
@r_arr = reverse(@arr); #r_arr为(6,5,4,3,2,1)
● join函数用于连接一个数组的所有元素,组成一个字符串,调用形式为:$string = join("seperator", @arr, ...)。例如:
@arr = (aa, bb, cc);
@str1 = join("-", @arr); #str1为"aa-bb-cc"
@str2 = joint(":", @arr, "hello", 100); #str2为"aa:bb:cc:hello:100"
● split函数与join正好相反,调用形式为:@arr = split("seperator", $str)。
%hash = (a, 1, b, 2, c, 3); #表示a对应的值为1,b对应的值为2,c对应的值为3
● 访问散列表元素,例如:
$hash{a}; #访问键a的值,结果为1
● 添加新元素,例如:
$hash{d} = 100; #添加键d的值为100
● 例子:
@fruit =(“apple”, 1, “banana”, 2, “orange”, 12),获取元素或修改元素值:$dict{“bananas”},$dict{“bananas”}=1。
上面的关联数组初始化也可以这样:@fruit = (“apple”=>1, “banana”=>2, “orange”=>12)。
● 删除元素,例如:
delete $hash{c};#结果%hash为:(a, 1, b, 2, d, 100)
● 判断散列表是否为空,例如:
if (%hash)
● 取散列表中所有键的函数:keys,例如:
@keys = keys(%hash); #@keys为:(a, b, d)
● 取散列表中所有value的函数:values,例如:
@values = values(%hash); #@values 为:(a, b, d)
● 循环读取所有的key-value对的函数:each,相当于c++中的关联容器的迭代器,例如:
while (@item = each(%hash)) {
...
}
● unless语句使用方式与if相同,但是语义与if语句相反,当条件不成立时执行then语句块。unless也有unless {} else {},当条件成立时执行else语句块。
● while语句与C语言类似。
● do-while语句与C语言类似。
● until语句使用方式与while相同,但是语义与while语句相反,当条件不成立时继续循环,当条件成立时结束。
● for语句与C语言类似。一个特别的例子:循环变量递增语句后可以用逗号表达式增加其他执行语句。
for ( $a = 1; $a < 10; $a++, print "the value of a is : $a=n" ) {
......
}
● foreach语句非常实用,可以*自动*依次获取数组变量中的每一个元素来执行循环,格式如下:
foreach 变量 (数组变量) {
}
foreach $var (@arr) {
}
● 循环控制语句有三种:next,last和redo,next相当于C语言中的continue;last相当于C语言中的break;而redo表示不进行循环条件的判断,再执行依次循环体,应该较少适用吧。
sub NAME {
code;
}
● 函数可以接收调用者传入的参数,参数通过数组@_传入,所以可以读取该数组来获取每一个参数。
● 通常函数调用方法:&NAME。
● 函数通过return语句返回一个值。
● 看一个例子吧:
sub add {
my $res = $_[0] + $_[1];
return $res;
}
$a = 1; $b = 2;
$c = &add($a, $b);
参数获取也可以使用对参数数组@_使用shift函数来实现,上面的add函数可以写成:
sub add {
my $a1 = shift(@_);
my $a2 = shift(@_);
my $res = $a1 + $a2;
return $res;
}
● 预定义子程序,如BEGIN和END函数,BEGIN函数就是在整个程序执行前被调用的函数,END是在整个程序结束后被调用的函数。其他先不深究了,用到的时候再说吧。
● 函数内部可以定义临时数据(C++中称为局部变量),可以使用local和my两个函数来定义临时数据,二者是有一定区别的,据说local还有很深奥的使用方法,这里也不深究了。local和my有一个最大区别是,local定义的临时数据会传递到嵌套调用的下一个函数中,而my定义的临时数据值在当前域中有效,也就是说:my定义的临时数据才是C++中通常意义的局部变量,所以对二者不是很清楚的话,使用my是更加保险滴!
open(HANDLE, "filename"); #获取读文件句柄
open(HANDLE, ">filename"); #获取写文件句柄,若文件存在则先清空内容再写
open(HANDLE, ">>filename"); #获取写文件句柄,若文件存在则在原内容之后追加
close(HANDLE); #关闭文件,参数为文件句柄
● 更高级的打开文件方式
为了保证可靠性,一般打开文件后需要判断打开文件是否成功,Perl中一般会这样写:
open(HANDLE, ...) || die ("Could not open file ***!\n$!");
open(HANDLE, ...) || warn ("Could not open file ***!\n$!");
二者的区别是,die会结束运行,warn只是输出警告信息然后继续往后执行。
$!是编译器给出的错误信息,看看下面的例子,假如打开一个不存在的文件test.txt:
open(HANDLE, ”test.txt“) || die ("Could not open file test.txt!\n");
会输出:
Could not open file test.txt!
如果架上$!,如下:
open(HANDLE, ”test.txt“) || die ("Could not open file test.txt!\n$!");
则会输出:
Could not open file test.txt!
No such file or directory at ./3.pl line 5. (该行是编译器给出的错误信息)
可以看出,这种打开文件的方法非常简练使用,所以差不多就成了标准写法吧。
● 读取文件
$a = <HANDLE>; #读取文件中的一行
读取后,文件指针会自动后移到下一行,因此可以用在循环中按行循环读取一个文件,例如:
while ( $line = <HANDLE> ) {
print $line;
}
@a = <HANDLE>; #将文件整个赋给数组@a,数组的每个元素对应文件的一行
详见:http://blog.csdn.net/taesimple/article/details/6307639
● 打开/读取/关闭目录
打开/关闭目录与操作文件类似,看下面的例子,读取该目录中所有的子目录和文件,做不同的处理:
opendir($handle, $path);
while($item = readdir($handle)) {
if(-d $item && !($dic =~ m/\.$|\.\.$/)) {
...
}
if ( -f $item ) {
...
}
}
closedir($handle);
● 关于当前目录
这是非常关键的,因为如果不是使用全局路径来操作文件或目录,都是相当于当前目录的,所以必须保证当前目录正确。
(获取当前目录)
有两种方法:
(1)
use Cwd;
my $dir = getcwd;
$dir中即为当前目录的完整路径信息。
(2)
my $dir = $ENV{'PWD'};
#ENV是一个散列,用于存放环境变量。$PWD是Linux的环境变量,表示当前所在目录。
(改变当前目录)
用chdir函数。
● 测试文件或目录
使用”-x 文件或目录名“的格式来测试文件或者目录的状态,-x文件测试操作符有很多不同的参数,常用的有:
-e: 是否存在
-d: 是否为目录
-f: 是否为普通文件
-r: 是否可读
-w: 是否可写
-x: 是否可执行
-l: 是否为符号链接
例如下面的例子表示,是否存在”test.txt"文件:
if ( -e "test.txt" )
● 其他文件操作函数
rename移动文件或者改名;unlink删除文件;chmod改变文件属性。
● 其他目录操作函数
mkdir创建目录,rmdir删除空目录。
● 特殊符号:*,?,.(含义不赘述了),其中“.”表示匹配*除了换行符以外*的任意一个字符。
● 关于转义处理,上面的特殊符号(*/?/.)有时候需要转义处理,因为这些特殊符号出现在匹配串中时有特殊含义,如果真的需要匹配这些字符时就要转义处理,例如要匹配“hello.”时,应该这样写:$str =~ /hello\./,如果不进行转义处理写成$str =~ /hello./的话表示,匹配hello后面跟上任意一个非换行字符。
如果特殊符号(*/?/.)出现在[ ]中则不用转义,例如要匹配:“hello.”和“hello!”,应该这样写:$str =~ /hello[.!]/,其中的"."不用进行转义处理。
● 锚定模式:\b匹配单词边界,\B匹配非单词边界,^和$匹配整个字符串的头部和末尾。
● 排除符号:^,跟匹配字符串头部的符号是一样的,但是只出现在[ ]中,表示“非“的含义, 例如:$str =~ /hello[^0-9abc]/表示hello后面紧接着的字符不是0-9或a或b或c。
● 管道符号:|,表示”或“的含义,可以将需要匹配的候选模式用”或“连接起来,例如:$str =~ /hello | hi/表示匹配”hello”或者匹配“hi"。
● 保存匹配片段,可以将匹配模式中的全部或者部分用括号扩起来,然后在匹配模式中引用或者在匹配完成后引用。
匹配模式中引用时使用\1、\2...,例如:
$str =~ /(\d{3})-\1/,解释:\d{3}表示连续的3个数字,用括号括起来表示一个保存的匹配片段,\1表示引用第一个匹配片段(即第一个括号里匹配的内容,匹配片段从左至右以1开始按顺序编号),所以该匹配模式匹配形如”123-123”、“010-010“的串。
$str =~ /(\w)(\w)-\1\2/,匹配的串例如:"ab-ab", "a1-a1", "aa-aa"等。
匹配结束后引用使用$1、$2...,例如:
if ( $res = $str =~ /([a-z]+)-([a-z]+)/ ) {
print "str1 : $1\n";
print "str1 : $2\n";
} #如果成功匹配的话,将匹配的两个匹配片段打印出来。
● 特殊符号的优先级:{ + * ? ( ) } 大于 { ^ $ \b \B } 大于 | 。
● 匹配选项:i,使用方式:/.../i,表示匹配时忽略大小写,例如:$str =~ /hello/i 可以成功匹配"hello", ”HELLO", "hELlo"等等。
● 匹配选项:g,使用方式:/.../g,表示匹配所有的串,默认情况下(不加g)一次匹配成功后便结束,但是有时候需要获取所有的匹配结果。例如串$str = "Today is 28 Nov, 2012, I am 20 years old.",现在需要获取其中所有的数,显然以前的匹配方式 $str =~ /\b\d+\b/只能匹配第一个数(28),如果要获取所有的数应该写成:$str =~ /\b\d+\b/g,但是当有多个匹配结果时,怎样获取结果呢?有两种方式,如下:
第一种:用while循环获取(代码如下),只要能成功匹配一次,while判断就为真,而且匹配表达式能自动的往后继续匹配。用$&获取匹配的结果($&通常包含满足最近匹配的字符串)。
#! /usr/bin/perl
$str = "This is an example.";
$match = "\\b[a-z]+\\b";
while ( $str =~ /$match/gi ) {
print "match : $&\n";
}
第二种:直接用数组一次获取匹配表达式的所有结果(代码如下),@res存储了所有成功匹配的字符串。
#! /usr/bin/perl
$str = "This is an example.";
$match = "\\b[a-z]+\\b";
@res = ( $str =~ /$match/gi );
foreach $item (@res) {
print "match : $item\n";
}
● 搜索并替换,格式为:$str =~ s/源串/替换串/。例如:$str =~ s/yes/no/,将串中的yes换成no。例如$str = "yes, great!",执行结果则为"no, great!"。
替换选项:g。如果$str = "yes, great! yes, wonderful!",则结果为“no, great! yes, wonderful!”,说明跟匹配是一样的,只替换第一个匹配串,如果需要替换所有匹配的串,可以用前面提到的g选项,所以可以写成:$str =~ s/yes/no/g,表示替换所有匹配串。
替换选项:i。表示忽略大小写,与匹配选项i是同样的意义,略。
表达式选项:e。表示替换串中支持可以计算的表达式。举个简单的例子,$str =~ s/the/9 * 9/ge表示替换所有的“the"为表达式“9 * 9“的结果,而不是替换为字符串”9 * 9",所以对于$str = "the dog is here!"执行结果为“81 dog is here!"。
● 搜索并翻译,用的比较少吧,通过下面的简单例子很好理解。
注意替换操作符s/string1/string2/和翻译操作符tr/string1/string2/的区别,前者查找string1并替换成string2,后者查找string1中的第一个字符替换为string2中的第一个字符,查找string1中的第二个字符替换为string2中的第二个字符,以此类推,也就是tr操作符不把string1和string2当做字符串而是一个个独立的字符。下面的例子显示了二者的区别。
$str = “abc123cba”;
$str =~ s/abc/xyz/; #结果str为:”xyz123cba”
$str = “abc123cba”;
$str =~ tr/abc/xyz/; #结果str为:”xyz123zyx”
● perl特有的指数运算符**,如2**3。
● chop截掉尾部的任意字符,而chomp只截掉换行符,一般处理STDIN的输入时用chomp函数,例如:
chomp($input = <STDIN>);
● 去掉标准输入的行尾换行符的另外一种方式,例如:
$in = <STDIN>;
print (“Hello world!\n”) if ($in eq “yes”);
终端输入yes,结果没有输出,这是因为$in末尾有换行符,可以用模式匹配删除掉,如下:
$in = <STDIN>;
$in =~ s/[\r\n]//;
print (“Hello world!\n”) if ($in eq “yes”);
● 字符串比较与数值比较:
字符串比较用:lt,gt,eq,le,ge,ne,cmp(比较,返回1,0,or-1)。数值比较用:<, >,==,<=, >=,!=,<=>(比较,返回1,0,or-1)。
需要注意的是,不能用数值比较符号去比较字符串,因为用数值符号比较时,会先把左右操作数转换为数值类型,非数字字符串转换结果为0。所以,例如:if (“abc”== “yes”) 判断结果为真!
● 比较运算符a <=> b,a大返回1,b大返回-1,相等返回0。
● 多行注释:
=pod
codes to comment
=cut
注意:=pod和=cut只能在行首,以=开头,以=cut结尾。
● 字符串连接用'.'运算符,例如:"hello"." "."world",结果为"hello world"。
● "abc"x3表示"abc"串重复3次,结果为"abcabcabc"。
● 普通变量“$”开头,数组变量“@”开头,关联数组“%”开头,另外访问数组或者关联数组的单个元素时以“$”开头。数组元素访问用“[]”,关联数组元素访问用“{}”,例如:
数组:@arr =(1,2,3),访问第三个元素:$arr[2];
关联数组:@fruit =(“apple”, 1, “banana”, 2, “orange”, 12),获取元素或修改元素值:$dict{“bananas”},$dict{“bananas”}=1。
上面的关联数组初始化也可以这样:@fruit = (“apple”=>1, “banana”=>2, “orange”=>12)。
● 使用正则表达式进行模式匹配时,$&为上一次匹配成功的字符串。
● 去掉行首或行尾的空白符(包括换行符)的正则表达式写法:
$inputline = <STDIN>;
$inputline =~ s/^\s+|\s+\n$//g;
● 使用正则表达式进行模式匹配时,$&为上一次匹配成功的字符串。
● 去掉行首或行尾的空白符(包括换行符)的正则表达式写法:
$inputline = <STDIN>;
$inputline =~ s/^\s+|\s+\n$//g;
前两天项目中遇到了一个Perl脚本程序,需要读懂该程序,由于以前重来没有用过Perl语言,所以没法搞定。今天抽空把该语言的基础看了一遍,基本上内读懂Perl脚本程序了吧。真是如网上很多分享的经验所说,第一:会一门语言后,学习其他的语言也就容易了,所有的语言包含的内容都差不多,只要熟悉一下该语言的语法就OK了;第二:会一门语言的有经验的开发者,跟本没有必要花大量的时间把一门新语言重头读到尾来学习他,看看基础就可以用了,用的过程中不明白的再去查阅手册或资料。
网上不少人说Perl语言受关注度越来越低,在服务器端慢慢的被PHP取代,但是作为系统脚本语言还是有他的特点的,我觉得最主要的是:强大的正则表达式和模式匹配功能,在sed和awk中也用到了类似的语法。
入门可以参考以下教程:
http://www.cbi.pku.edu.cn/chinese/documents/perl/index.htm
http://www.phpchina.com/resource/manual/perl/perl5-1.htm
下面是我学习中记下的一些基础知识,当作备忘吧。
【数组】
● 首先说一种数据类型,将“列表”,例如:(1, 2, 3),(1, 2, "hello", $name, 10)。● 连续数值的列表有缩写形式,例如:(1 .. 10),(1, 3, 5 .. 10);浮点型的(0.5 .. 3.8)表示(0.5, 1.5, 2.5, 3.5); 字符型的(a .. z)表示小写字母a到z。
● 数组变量以@开头,可以定义与简单变量相同的名字,$var和@var不冲突。
● 数组可以直接给普通变量赋值,例如:
@arr = (1 .. 3);
($a, $b) = @arr; #a为1, b为2
($c, $d, $e, $f) = @arr; #c为1, d为2, e为3, f为null
● qw函数创建字符串数组,不需要使用逗号和引号,例如:
@arr = qw(aaa bbb ccc ddd);
● 可以从标准输入读入数组,按CTRL+D结束输入,例如:
@arr = <STDIN>;
● 访问数组的某个元素,用$,数组下标从0开始,例如:
@arr = (1 .. 3);
$arr[0]; $arr[1]; $arr[2]; 分别访问数组第1、2、3个元素。
● 获取数组长度:$len = @arr;
● 数组截取(用@),(注意规则是:取多个数组元素用@,取单个数组元素用$。)例如:
@arr = (1 .. 6);
@sub1 = @arr[0, 2, 4]; #sub1为(1, 3, 5)
@sub2 = @arr[1, 3, 5]; #sub1为(2, 4, 6)
@sub1 = @arr[0, 3..5]; #sub1为(1, 4, 5, 6)
● 数组访问支持负数下标,例如:
@arr = (1, 2, 3);
$item = $arr[-1]; #item为3
$sub = @arr[0, -1]; #sub为(1,3)
(作用于数组的函数)
● chop和chomp函数可用于数组,例如:chomp(@arr)用于去掉arr中所有字符串尾部的换行符。
● push和pull操作数组相当于栈操作,数组的右边界为栈的顶部,即从右边“弹出”或者“压入”元素。
● sort用于对数组元素进行排序,调用形式为:@sorted = sort(@arr); 执行sort函数后原数组不会改变,所以要通过返回值接收排好序的数组。默认情况下,按所有元素的ASCII顺序排序(包括数字),所以不能简单调用sort函数对数值型元素排序。如果需要按数值大小进行排序,应该这样调用:
升序:@sorted = sort { $a <=> $b } @arr;
降序:@sorted = sort { $b <=> $a } @arr;
● reverse函数用于反转一个数组,例如:
@arr = (1 .. 6);
@r_arr = reverse(@arr); #r_arr为(6,5,4,3,2,1)
● join函数用于连接一个数组的所有元素,组成一个字符串,调用形式为:$string = join("seperator", @arr, ...)。例如:
@arr = (aa, bb, cc);
@str1 = join("-", @arr); #str1为"aa-bb-cc"
@str2 = joint(":", @arr, "hello", 100); #str2为"aa:bb:cc:hello:100"
● split函数与join正好相反,调用形式为:@arr = split("seperator", $str)。
【散列表(hash表,关联数组)】
● 散列变量以%开头,例如:%hash = (a, 1, b, 2, c, 3); #表示a对应的值为1,b对应的值为2,c对应的值为3
● 访问散列表元素,例如:
$hash{a}; #访问键a的值,结果为1
● 添加新元素,例如:
$hash{d} = 100; #添加键d的值为100
● 例子:
@fruit =(“apple”, 1, “banana”, 2, “orange”, 12),获取元素或修改元素值:$dict{“bananas”},$dict{“bananas”}=1。
上面的关联数组初始化也可以这样:@fruit = (“apple”=>1, “banana”=>2, “orange”=>12)。
● 删除元素,例如:
delete $hash{c};#结果%hash为:(a, 1, b, 2, d, 100)
● 判断散列表是否为空,例如:
if (%hash)
● 取散列表中所有键的函数:keys,例如:
@keys = keys(%hash); #@keys为:(a, b, d)
● 取散列表中所有value的函数:values,例如:
@values = values(%hash); #@values 为:(a, b, d)
● 循环读取所有的key-value对的函数:each,相当于c++中的关联容器的迭代器,例如:
while (@item = each(%hash)) {
...
}
【控制结构】
● if语句与C语言类似,不同的是C语言中的else if应该写成elsif。● unless语句使用方式与if相同,但是语义与if语句相反,当条件不成立时执行then语句块。unless也有unless {} else {},当条件成立时执行else语句块。
● while语句与C语言类似。
● do-while语句与C语言类似。
● until语句使用方式与while相同,但是语义与while语句相反,当条件不成立时继续循环,当条件成立时结束。
● for语句与C语言类似。一个特别的例子:循环变量递增语句后可以用逗号表达式增加其他执行语句。
for ( $a = 1; $a < 10; $a++, print "the value of a is : $a=n" ) {
......
}
● foreach语句非常实用,可以*自动*依次获取数组变量中的每一个元素来执行循环,格式如下:
foreach 变量 (数组变量) {
}
foreach $var (@arr) {
}
● 循环控制语句有三种:next,last和redo,next相当于C语言中的continue;last相当于C语言中的break;而redo表示不进行循环条件的判断,再执行依次循环体,应该较少适用吧。
【函数】
● 函数定义以sub开头,格式如下:sub NAME {
code;
}
● 函数可以接收调用者传入的参数,参数通过数组@_传入,所以可以读取该数组来获取每一个参数。
● 通常函数调用方法:&NAME。
● 函数通过return语句返回一个值。
● 看一个例子吧:
sub add {
my $res = $_[0] + $_[1];
return $res;
}
$a = 1; $b = 2;
$c = &add($a, $b);
参数获取也可以使用对参数数组@_使用shift函数来实现,上面的add函数可以写成:
sub add {
my $a1 = shift(@_);
my $a2 = shift(@_);
my $res = $a1 + $a2;
return $res;
}
● 预定义子程序,如BEGIN和END函数,BEGIN函数就是在整个程序执行前被调用的函数,END是在整个程序结束后被调用的函数。其他先不深究了,用到的时候再说吧。
● 函数内部可以定义临时数据(C++中称为局部变量),可以使用local和my两个函数来定义临时数据,二者是有一定区别的,据说local还有很深奥的使用方法,这里也不深究了。local和my有一个最大区别是,local定义的临时数据会传递到嵌套调用的下一个函数中,而my定义的临时数据值在当前域中有效,也就是说:my定义的临时数据才是C++中通常意义的局部变量,所以对二者不是很清楚的话,使用my是更加保险滴!
【文件和目录操作】
● 打开与关闭文件open(HANDLE, "filename"); #获取读文件句柄
open(HANDLE, ">filename"); #获取写文件句柄,若文件存在则先清空内容再写
open(HANDLE, ">>filename"); #获取写文件句柄,若文件存在则在原内容之后追加
close(HANDLE); #关闭文件,参数为文件句柄
● 更高级的打开文件方式
为了保证可靠性,一般打开文件后需要判断打开文件是否成功,Perl中一般会这样写:
open(HANDLE, ...) || die ("Could not open file ***!\n$!");
open(HANDLE, ...) || warn ("Could not open file ***!\n$!");
二者的区别是,die会结束运行,warn只是输出警告信息然后继续往后执行。
$!是编译器给出的错误信息,看看下面的例子,假如打开一个不存在的文件test.txt:
open(HANDLE, ”test.txt“) || die ("Could not open file test.txt!\n");
会输出:
Could not open file test.txt!
如果架上$!,如下:
open(HANDLE, ”test.txt“) || die ("Could not open file test.txt!\n$!");
则会输出:
Could not open file test.txt!
No such file or directory at ./3.pl line 5. (该行是编译器给出的错误信息)
可以看出,这种打开文件的方法非常简练使用,所以差不多就成了标准写法吧。
● 读取文件
$a = <HANDLE>; #读取文件中的一行
读取后,文件指针会自动后移到下一行,因此可以用在循环中按行循环读取一个文件,例如:
while ( $line = <HANDLE> ) {
print $line;
}
@a = <HANDLE>; #将文件整个赋给数组@a,数组的每个元素对应文件的一行
详见:http://blog.csdn.net/taesimple/article/details/6307639
● 打开/读取/关闭目录
打开/关闭目录与操作文件类似,看下面的例子,读取该目录中所有的子目录和文件,做不同的处理:
opendir($handle, $path);
while($item = readdir($handle)) {
if(-d $item && !($dic =~ m/\.$|\.\.$/)) {
...
}
if ( -f $item ) {
...
}
}
closedir($handle);
● 关于当前目录
这是非常关键的,因为如果不是使用全局路径来操作文件或目录,都是相当于当前目录的,所以必须保证当前目录正确。
(获取当前目录)
有两种方法:
(1)
use Cwd;
my $dir = getcwd;
$dir中即为当前目录的完整路径信息。
(2)
my $dir = $ENV{'PWD'};
#ENV是一个散列,用于存放环境变量。$PWD是Linux的环境变量,表示当前所在目录。
(改变当前目录)
用chdir函数。
● 测试文件或目录
使用”-x 文件或目录名“的格式来测试文件或者目录的状态,-x文件测试操作符有很多不同的参数,常用的有:
-e: 是否存在
-d: 是否为目录
-f: 是否为普通文件
-r: 是否可读
-w: 是否可写
-x: 是否可执行
-l: 是否为符号链接
例如下面的例子表示,是否存在”test.txt"文件:
if ( -e "test.txt" )
● 其他文件操作函数
rename移动文件或者改名;unlink删除文件;chmod改变文件属性。
● 其他目录操作函数
mkdir创建目录,rmdir删除空目录。
【正则表达式】
● 基本模式:$str =~ /abc/表示在字符串变量$str中匹配"abc",$str !~ /abc/表示在字符串变量$str中*不*匹配"abc"(即不含“abc”)。匹配表达式可以返回真假结果值,例如:$match = ($str =~ /abc/),如果匹配成功则$match为真,否则为假,也可以作为条件判断,例如:if ($match = ($str =~ /abc/) ) 或者直接用匹配表达式判断: if ($str =~ /abc/ )。● 特殊符号:*,?,.(含义不赘述了),其中“.”表示匹配*除了换行符以外*的任意一个字符。
● 关于转义处理,上面的特殊符号(*/?/.)有时候需要转义处理,因为这些特殊符号出现在匹配串中时有特殊含义,如果真的需要匹配这些字符时就要转义处理,例如要匹配“hello.”时,应该这样写:$str =~ /hello\./,如果不进行转义处理写成$str =~ /hello./的话表示,匹配hello后面跟上任意一个非换行字符。
如果特殊符号(*/?/.)出现在[ ]中则不用转义,例如要匹配:“hello.”和“hello!”,应该这样写:$str =~ /hello[.!]/,其中的"."不用进行转义处理。
● 锚定模式:\b匹配单词边界,\B匹配非单词边界,^和$匹配整个字符串的头部和末尾。
● 排除符号:^,跟匹配字符串头部的符号是一样的,但是只出现在[ ]中,表示“非“的含义, 例如:$str =~ /hello[^0-9abc]/表示hello后面紧接着的字符不是0-9或a或b或c。
● 管道符号:|,表示”或“的含义,可以将需要匹配的候选模式用”或“连接起来,例如:$str =~ /hello | hi/表示匹配”hello”或者匹配“hi"。
● 保存匹配片段,可以将匹配模式中的全部或者部分用括号扩起来,然后在匹配模式中引用或者在匹配完成后引用。
匹配模式中引用时使用\1、\2...,例如:
$str =~ /(\d{3})-\1/,解释:\d{3}表示连续的3个数字,用括号括起来表示一个保存的匹配片段,\1表示引用第一个匹配片段(即第一个括号里匹配的内容,匹配片段从左至右以1开始按顺序编号),所以该匹配模式匹配形如”123-123”、“010-010“的串。
$str =~ /(\w)(\w)-\1\2/,匹配的串例如:"ab-ab", "a1-a1", "aa-aa"等。
匹配结束后引用使用$1、$2...,例如:
if ( $res = $str =~ /([a-z]+)-([a-z]+)/ ) {
print "str1 : $1\n";
print "str1 : $2\n";
} #如果成功匹配的话,将匹配的两个匹配片段打印出来。
● 特殊符号的优先级:{ + * ? ( ) } 大于 { ^ $ \b \B } 大于 | 。
● 匹配选项:i,使用方式:/.../i,表示匹配时忽略大小写,例如:$str =~ /hello/i 可以成功匹配"hello", ”HELLO", "hELlo"等等。
● 匹配选项:g,使用方式:/.../g,表示匹配所有的串,默认情况下(不加g)一次匹配成功后便结束,但是有时候需要获取所有的匹配结果。例如串$str = "Today is 28 Nov, 2012, I am 20 years old.",现在需要获取其中所有的数,显然以前的匹配方式 $str =~ /\b\d+\b/只能匹配第一个数(28),如果要获取所有的数应该写成:$str =~ /\b\d+\b/g,但是当有多个匹配结果时,怎样获取结果呢?有两种方式,如下:
第一种:用while循环获取(代码如下),只要能成功匹配一次,while判断就为真,而且匹配表达式能自动的往后继续匹配。用$&获取匹配的结果($&通常包含满足最近匹配的字符串)。
#! /usr/bin/perl
$str = "This is an example.";
$match = "\\b[a-z]+\\b";
while ( $str =~ /$match/gi ) {
print "match : $&\n";
}
第二种:直接用数组一次获取匹配表达式的所有结果(代码如下),@res存储了所有成功匹配的字符串。
#! /usr/bin/perl
$str = "This is an example.";
$match = "\\b[a-z]+\\b";
@res = ( $str =~ /$match/gi );
foreach $item (@res) {
print "match : $item\n";
}
● 搜索并替换,格式为:$str =~ s/源串/替换串/。例如:$str =~ s/yes/no/,将串中的yes换成no。例如$str = "yes, great!",执行结果则为"no, great!"。
替换选项:g。如果$str = "yes, great! yes, wonderful!",则结果为“no, great! yes, wonderful!”,说明跟匹配是一样的,只替换第一个匹配串,如果需要替换所有匹配的串,可以用前面提到的g选项,所以可以写成:$str =~ s/yes/no/g,表示替换所有匹配串。
替换选项:i。表示忽略大小写,与匹配选项i是同样的意义,略。
表达式选项:e。表示替换串中支持可以计算的表达式。举个简单的例子,$str =~ s/the/9 * 9/ge表示替换所有的“the"为表达式“9 * 9“的结果,而不是替换为字符串”9 * 9",所以对于$str = "the dog is here!"执行结果为“81 dog is here!"。
● 搜索并翻译,用的比较少吧,通过下面的简单例子很好理解。
注意替换操作符s/string1/string2/和翻译操作符tr/string1/string2/的区别,前者查找string1并替换成string2,后者查找string1中的第一个字符替换为string2中的第一个字符,查找string1中的第二个字符替换为string2中的第二个字符,以此类推,也就是tr操作符不把string1和string2当做字符串而是一个个独立的字符。下面的例子显示了二者的区别。
$str = “abc123cba”;
$str =~ s/abc/xyz/; #结果str为:”xyz123cba”
$str = “abc123cba”;
$str =~ tr/abc/xyz/; #结果str为:”xyz123zyx”
【其他杂项】
● print可以加括号也可以不加。● perl特有的指数运算符**,如2**3。
● chop截掉尾部的任意字符,而chomp只截掉换行符,一般处理STDIN的输入时用chomp函数,例如:
chomp($input = <STDIN>);
● 去掉标准输入的行尾换行符的另外一种方式,例如:
$in = <STDIN>;
print (“Hello world!\n”) if ($in eq “yes”);
终端输入yes,结果没有输出,这是因为$in末尾有换行符,可以用模式匹配删除掉,如下:
$in = <STDIN>;
$in =~ s/[\r\n]//;
print (“Hello world!\n”) if ($in eq “yes”);
● 字符串比较与数值比较:
字符串比较用:lt,gt,eq,le,ge,ne,cmp(比较,返回1,0,or-1)。数值比较用:<, >,==,<=, >=,!=,<=>(比较,返回1,0,or-1)。
需要注意的是,不能用数值比较符号去比较字符串,因为用数值符号比较时,会先把左右操作数转换为数值类型,非数字字符串转换结果为0。所以,例如:if (“abc”== “yes”) 判断结果为真!
● 比较运算符a <=> b,a大返回1,b大返回-1,相等返回0。
● 多行注释:
=pod
codes to comment
=cut
注意:=pod和=cut只能在行首,以=开头,以=cut结尾。
● 字符串连接用'.'运算符,例如:"hello"." "."world",结果为"hello world"。
● "abc"x3表示"abc"串重复3次,结果为"abcabcabc"。
● 普通变量“$”开头,数组变量“@”开头,关联数组“%”开头,另外访问数组或者关联数组的单个元素时以“$”开头。数组元素访问用“[]”,关联数组元素访问用“{}”,例如:
数组:@arr =(1,2,3),访问第三个元素:$arr[2];
关联数组:@fruit =(“apple”, 1, “banana”, 2, “orange”, 12),获取元素或修改元素值:$dict{“bananas”},$dict{“bananas”}=1。
上面的关联数组初始化也可以这样:@fruit = (“apple”=>1, “banana”=>2, “orange”=>12)。
● 使用正则表达式进行模式匹配时,$&为上一次匹配成功的字符串。
● 去掉行首或行尾的空白符(包括换行符)的正则表达式写法:
$inputline = <STDIN>;
$inputline =~ s/^\s+|\s+\n$//g;
● 使用正则表达式进行模式匹配时,$&为上一次匹配成功的字符串。
● 去掉行首或行尾的空白符(包括换行符)的正则表达式写法:
$inputline = <STDIN>;
$inputline =~ s/^\s+|\s+\n$//g;
相关文章推荐
- C语言基础知识备忘
- 【Android】基础知识点备忘
- 网络基础知识备忘
- Perl Web 门户基础知识(Plack,cpanm)
- tcp/ip学习----基础知识备忘
- 了解 Perl/Tk 模块,第 1 部分 Perl/Tk 基础知识
- Perl基础知识(第二章)
- c#基础知识备忘(二)
- 华为vlan基础知识随记备忘
- perl基础知识01【perl用处】
- perl基础知识03【语法】
- 基础知识备忘——字段(Field),属性(Property),特性(Attribute)
- JDBC基础知识(备忘)
- perl基础知识02【代码执行格式】
- perl的基础知识总结-----易混淆但有用特殊符号
- 借助幕课网的资源重新梳理下PHP基础知识,用以备忘。
- perl基础知识06【转义与元字符与特殊字符】
- Perl基础知识
- 网络基础知识备忘
- Java Web 基础知识备忘