Perl learning 笔记
Perl 的默认规则:
关于括号:如果括号不能改变语句的意义,则其就是可选的
设计哲学:没有不必要的限制
1 Chapter 1 perl 语言学习的准备:
l Perl擅长处理文本,短时间内完成的程序;
l #!/usr/bin/perl 开头,或者#!/usr/bin/env perl;
l Perl 中不需要声明变量,没有“main”程序;
2 Chapter 2 标量数据
2.1 数字
l 数字和字符串都是标量数据;
l 数字的格式不同,但内部都是double float来处理;
l 数字操作符+ - * / %(先转换成整数再取模) x**y 表示x的y次方;
2.2 字符串
l 单引号字符串:/n不被当作特殊字符,除非//n,如果要表示单引号,使用/’;
l 双引号字符串:转移字符/n等当作特殊字符(换行)处理;
l 字符串操作:用“.”符号连接
2.3 警告
l perl –w test.pl 或者在test.pl内部加入#!/usr/bin/perl –w
l warning在perl中加入 use warnings;
2.4 标量变量
l 大小写区分,由$开头,
l 标量变量赋值:$number=10; $binary=’hello’;
l 赋值支持二元赋值,$number+=5;
2.5 Print
l Print “this is a test”; print “The number is $number”; print $binary;
l 如果双引号中$变量前没有/,那么打印的值就被标量真实值取代;而如果是单引号打印,即使$前没有/,也不会被替代 print ‘this is $number’;(打印出this is $number)
l {}用于表示分隔符
l 比较运算符:
数字 字符串
== eq
!= ne
< lt
> gt
<= le
>= ge
l If 判断:如果使用上面的比较判断,可以使用if(){}来进行判定,{}是必须的
2.6 Boolean
l Perl 中没有boolean类型,但它依靠一些规则来处理:
Ø 如果值为数字,0为false,其他为真
Ø 如果值为字符串,空串(‘’)为false,其他为真;
Ø 如果值的类型不是数字也不是字符串,则转换成数字或字符串之后再运用上面规则
Ø 例外:字符串‘0’和数字0 有相同的标量值,所以字符串‘0’是唯一一个非空,但值为0的串(‘0’为false)
Ø 如果要得到相反值,使用 一元非运算符 ! if(! $if_bigger){}
2.7 用户输入<STDIN>
<STDIN>作为标量使用,一般指键盘输入,也可以通过其他输入(行输入运算符对文件句柄STDIN操作)
$line=<STDIN>;
这个时候$line就包含用户输入的所有内容(包含换行符/n),所以一般需要去掉/n(使用chomp)
2.8 Chomp
Chomp对变量起作用,如果字符串变量含有换行符,则去掉换行符。
$line=”this is a test line/n”;
Chomp($line); #去掉了$line的换行符
² 如果结尾有两个或两个以上的换行符,只去掉一个。
2.9 while 循环
2.10 undef值
perl中的变量不需要初始化,但这些值其实被初始化成了undef值,对于数字,它认为是0,对于字符串认为是空串。
3 Chapter 3列表和数组
² 列表是标量的有序集,数组是包含列表的变量。
² 列表或数组中每一个元素都是一个独立的标量,但通常他们的数据类型也相同。
² 列表和数组的索引起始为0;
3.1 访问数组元素
l $fred[0], $fred[1]等形式访问数组元素,同时也可以按标量变量进行操作。
l 数组的赋值可以不连续,没有被赋值的元素值为undef
l 可以使用$#arrayname表示最后的索引值(数组的个数为$#arrayname+1)
3.2 XX
3.3 列表
l (1,2,3)表示含有1,2,3的列表
(1 .. 5) 含有1,2,3,4,5的列表
(“fred”, “tom”, “Jack”)
l qw简写:
qw(fred tom jack)同上面一样,但省略的引号,分隔符可以使用很多如qw{}, qw(), qw<>, qw!!
3.4 列表赋值
l 可以直接赋值,($fred,$tom)=(”fred”,”tom”);
l 也可以通过qw来赋值
l 使用@name_of_array来对整个数组进行赋值
Ø @rocks= qw /xxx xxx xxx/;
Ø @copy=@quarry;#数组copy
3.4.1 Pop and push
pop 操作将数组的最后一个元素取出并返回
@array = 5..9;
$fred = pop(@array); #$fred 得到 9,@array 现在为(5,6,7,8)
$barney = pop @array; #$barney gets 8, @array 现在为(5,6,7)
pop @array; #@array 现在为(5,6)(7 被丢弃了)
push 操作将一个元素或一列元素加入数组末尾
push(@array,0); #@array 现在为(5,6,0)
push @array,8; #@array 现在为(5,6,0,8)
push @array,1..10; #@array 现在多了 10 个元素
@others =qw/9 0 2 1 0 /;
push @array,@others; #@array 现在又多了 5 个元素(共有 19 个)
push 的第一个参数或者 pop 的唯一参数必须是数组变量。
3.4.2 shift and unshift
push 和 pop 对数组的末尾进行操作, unshift 和shift 对一个数组的开头进行操作
3.5 将数组插入字符串
注意一些转义字符
3.6 Foreach 控制结构
Foreach用于处理整个数组或列表
foreach $rocks (@rocksarray){}
3.6.1 默认变量$_
如果foreach循环中省略了控制变量,perl 就使用默认的$_
foreach(1..10){ #使用默认的变量$_
print “I can count to $_!/n”;
}
3.6.2 reverse操作
将输入的一串列表反向输出,赋值到新的列表中去(不改变原来列表的循序)
3.6.3 sort 操作
将输入的一串列表或数组按字符顺序排序(对纯数字无意义),并赋值到新的数组中
3.7 标量和列表上下文
@list = @people; #3 个 People 的列表
$n = @people ; #数字 3
如果要强制转换标量context,使用scalar函数,如scalar @rocks将返回rocks的成员个数。
3.8 <STDIN>在列表Context中
@lines=<STDIN> 将输入读入列表Context中
chomp (@lines = <STDIN>); #读入所有的行,不包括换行符
4 Chapter 4子程序
4.1 定义一个子程序
sub xxxx{
}
l 子程序的定义是全局的,无需提前声明,放在程序的那里都可以
4.2 调用子程序
用&subfunction_name
4.3 返回值
程序中最后一个被计算的表达式的值为返回值
4.4 参数
子程序的参数被存放在 @_数组中,或者说子程序的参数第一个值在$_[0]中,第二个在$_[1]中。
@_是子程序的一个私有变量,不会影响到原有的全局变量。
4.5 子程序中的私有变量
使用my来创建私有变量,否则就是全局变量
其他地方同名字的变量不会影响,也不能访问这些私有变量。
4.6 参数个数
子程序中的参数个数可以不确定,当然也可以检查个数,使用:
If(@_!=n)#@_此时表示标量,参数的个数
4.7 my变量
my变量可以在任意块中使用。对每个标量的声明,都要加上my
4.8 使用 strict Pragma
4.9 返回操作和&的使用
l 返回值不必要return xxx,当然加上也可以
l 当perl知道这个子程序时可以省略&,如果是自定义的子程序,并且和内嵌的一些函数同名,那就要加上&才能确保使用自定义的子程序
5 Chapter 5 输入和输出
5.1 标准输入<STDIN>
chomp($line=<STDIN>)
while(<STDIN>){
print “I saw $_”;
}
foreach(<STDIN>){
print “I saw $_”;
}
在 while 循环中,Perl 读入一行,将它赋给变量,然后进入循环。再回到开头,读入下一行。但
在 foreach 循环中,由于行输入操作在列表的 context 中使用,因为 foreach 需要一个列表作为其参数。因此,它在循环执行
前会将所有的输入读入
5.2 <>输入
<>从Perl的默认变量@ARGV中取参数
while(<>){
chomp;
print “It was $_ that I saw!/n”;
}
5.3 输出到标准输出
print “@array”; 打印一个列表中的所有元素;
print 可以当成函数调用(加括号),也可以不当成调用
5.4 使用printf标准输出
5.5
5.6 句柄
文件句柄(filehandle)是 Perl 程序 I/O 连接的名字,是 Perl 和外界的纽带。也就是说,它是连接的名字,而非文件的名字.
Perl 自身有六个文件句柄:STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT
#./your_program <dino >Wilma
上述命令告诉 shell,从一个名叫 dino 读入,将结果输出到叫做 wilma 的文件之中
#cat fred barney | sort | ./your_program | grep something | lpr
如果你不熟悉 Unix 命令,也不要紧。上面一行的含义是:cat 命令将输出文件 fred 的所有行,紧接着是文件 barney 的所有行。这个输出作为 sort 的输入,它将所有的输入的行进行排序,再将结果传递给 your_program。经过 your_program 处理后,将结果传给 grep,它会将某些行去除掉,然后送给 lpr,它会将传给它的数据打印出来
5.7 文件句柄的打开
使用自定义的文件句柄:
open CONFIG, “dino”;#打开名为CONFIG的文件句柄,从dino输入
open CONFIG, “<dino”;#和上面一样
open BEDROCK, “>fred”;#打开文件句柄,将结果输入文件fred
open LOG, “>>logfile”;#打开文件句柄, 追加到logfile文件末尾
5.7.1 Bad文件句柄
使用下面进行检测文件句柄的打开
my $success = open LOG, “>>logifle”; #将返回值保存在$success 中
if(!$success){
#打开失败时
...
}
5.7.2 关闭文件句柄
close BEDROCK;
关闭文件句柄将清空缓存,并释放文件的锁。
5.8 严重错误和die
die 函数将打印出你给它的消息(利用标准错误流),并确保程序退出时为非零(nonzero)的退出状态(exit status)
if(!open LOG, “>>logfile”){
die “Cannot create logfile:$!”;
}
如果 open 失败,则 die 将结束程序,并告诉你不能创建 logfile
die 还会为你做一件事:他会自动将 Perl 程序的名字和行数输出在消息的末尾,因此能轻易的辨别出是哪一个 die 引起的错误, 如果不需要运行名字和行号,加上换行符/n,(程序运行名在$0中)
5.9 使用文件句柄
文件句柄被打开当作输入时,可以跟STDIN类似的使用;
对于输出文件句柄,可以和print或printf结合使用
print LOG “Captain’s log, stardate 3.14159/n”; #输出到 LOG 中,文件句柄和要打印的内容之间无逗号。
5.9.1 改变默认的输出句柄
默认输出到STDOUT,通过select进行修改
open BEDROCK, “>fred”;
select BEDROCK;
print “this is a test for select output”;
select STDOUT;
print “this is for output to STDOUT”;
默认情况,输出到文件句柄的内容会被缓存起来。将变量$|设置为1,将会在输出操作结束时会立刻清空文件句柄
5.10 重新打开文件句柄
如果重新打开一个文件句柄,前一个同名的句柄将被自动关闭。
#将出错信息送到私有错误日志上
if(! Open STDERR, “>>/home/barney/.error_log”){
die “Can’t open error log for append: $!”;
}
6 Chapter 6 哈希hash
6.1 什么是哈希
哈希是一种数据结构,和数组类似,可以将值存放到其中,或者从中取回值。和数组不同的是,其索引不是数字,而是名字(任意唯一的字符串)
没有确定的顺序,因此也没有第一个元素。只是一些 key/value 对的集合
keys 和 values 均为任意的标量,但 keys 通常转换为字符串
6.1.1 为什么使用哈希
可以把 hash 看作一个简单的数据库,其中每一个 key 下面可以有一块数据,key是唯一的。。如果你的任务是关于: “查询重复的”,“唯一的”,“交叉引用的”,“查询表”,则 hash 很可能在这类应用中帮上你的忙
6.2 哈希元素的存取
要访问 hash 元素,可以使用下面的语法:
$family_name{“fred”} = “flintstone”;
Key使用{}来标记,当在名字前面是美元符号($),后面是花括号({}),则其为 hash 元素
当将某个值存储在已经存在的 hash 元素中,以前的值会被覆盖
6.2.1 作为整体的hash
要引用整个 hash,使用百分号(“%”)作为前缀。前面几页中使用的 hash 的名字为%family_name
为了方便,哈希和列表之间可以互换。
虽然可以使用任何列表表达式,但其列表元素个数必须是偶数,因为由 key/value 对组成
%some_hash = (“foo”, 35, “bar”, 12.4, 2.5, “hello”, “wilma”, 1.72e30, “betty”, “bye/n”);
@array_array = %some_hash
6.2.2 哈希赋值
%new_hash = %old_hash;
%inverse_hash = reverse %any_hash;
(key,value,key,value,key,value,…… )->(value,key,value,key,value,key,…… )(注意:最后一次赋值获胜 规则)
6.2.3 大箭头=>
哈希赋值时
my %last_name = (
“fred” => “flintstone”,
“dino” => undef,
“barney”=> “rubble”;
“betty”=> “rubble”,
);
6.3 哈希函数
6.3.1 keys and values函数
keys函数返回hash所有keys,values函数返回所有valuses
my %hash = (“a”=>1, “b”=>2, “c”=>3);
my @k = keys %hash;
my @v = values %hash;
my $count = keys %hash; #得到 3,是指有 3 个 key/value 对
6.3.2 each 函数
迭代hash的每一个元素,它将返回 key/value 对的2元素
列表
while (($key, $value) = each %hash){
print “$key => $value/n”;
}
6.4 哈希的通常用法
if($books{$someone}){
print “$someone has at least one book checked out./n”;
}
6.4.1 exits函数
查看hash中是否存在某个key
if(exists $books{$dino}){
print “Hey, there’s a libaray card for dino!/n”;
}
6.4.2 delete函数
delete 函数将某个给定的 key(包括其对应的 value)从 hash 中删除。
delete $books{$person}; #将$person 的借书卡删除掉