Perl 复习整理

摘录整理自 learning perl 7e

标量数据

字符串操作符

字符串连接操作符:.

1
2
3
4
5
"hello". "world" # 同于"helloworld"

"hello". " ". "world" #同于"hello world"

"hello world". "\n" #同于"hello world\n"

字符串重复操作符:x ,把操作符左边字符串 重复操作符右边数字那么多次:

1
2
3
4
5
6
"fred"x 3 # "fredfredfred"
"barney"x (4+1) # "barney"x 5, "barneybarneybarneybarneybarney"
5 x 4.8
5 x 0.2
#实际上是"5"x 4, "5555"
#实际上是"5"x 0, 空字符串

数字和字符串之间的自动转换

Perl 将在需要的时候自动在数字和字符串之间转换。关键在于操作符。
•操作符(如+)需要数字,Perl 将把操作数当作数字看待。
•操作符需要字符串(如. ),Perl 将把操作数当作字符串看待。

1
2
3
"12"* "3"           #36
"12fred34"* "3" #36
"fred"* "3" #0

布尔值

Perl 没有Boolean 类型,仅靠一些简单的规则来判断真假:

– 如果值为数字,0 是false;其余为真

– 如果值为字符串,则空串(“”)为false;其余为真

– 如果值的类型既不是数字又不是字符串,则将其转换为数字或字符串后再利用上述规则

“0”是唯一的非空false字符串

比较操作符

比较关系 数字 字符串
相等 == eq
不等 != ne
大于 > gt
小于 < lt
大于等于 >= ge
小于等于 <= le

chomp 操作符

  • chomp (),返回值?

    移除的字符数

  • 结尾有两个换行符,chomp去掉几个?

  • chomp() 与chop() ?

defined 函数

​ 要分辨其是undef 还是空串,可以使用defined 函数,

​ 它将在为undef 时返回false,其余返回true

列表与数组

列表直接量-list literal

圆括号内用逗号隔开的一串数据

1
2
3
4
5
6
7
(1,2,3) #含有1,2,3 的列表 

(1,2,3,) #同上,最后一个逗号被忽略

() #空列表-0 个元素

(1 ..100) #包含100 个整数的列表

范围操作符:..从左到右计数,每次加1

1
2
3
4
5
6
7
(1 ..5) #同(1,2,3,4,5) 

(1.7..5.7) #同上— 转换成整数

(5 ..1) #空— ..左值应小于右值,否则为空**

(0 .. $#rocks) #数组rocks的所有索引数字

qw 简写

Perl 将它们当作单引号字符串处理,不能像双引号那样在qw 中使用(\n) ($fred)

#qw自动忽略空白(空格、制表符、换行符)

使用圆括号作为定界符,perl允许用其他标点符号

数组

数组名字(fred)和标量属于完全不同的命名空间。
同一程序可以同时包含$fred(标量变量)和@fred命名的数组。

负数数组索引:从数组的尾端往回计数。
超出数组大小的负数索引值,返回undef,不会绕回数组尾部。

最后一个元素的索引 $end = $#rocks;

列表相关操作: 赋值

1
2
3
($fred, $barney, $dino) = ("flintstone", "rubble", undef);

($fred, $barney) = qw <flintstone rubble slate>; #一个值被忽略了

数组末尾:pop 和push 操作

pop 将数组的最后一个元素取出并返回

push,将一个元素(或一列元素)加在数组的末尾

1
push(@array,0);

数组开头:shift 和unshift 操作

同上

对数组中间操作:splice操作符

对数组的中间元素进行操作(四个参数)

  • 参数1:要操作的目标数组
  • 参数2:要操作的一组元素的开始位置
  • 参数3:指定要操作的元素长度(可选)
  • 参数4:要替换的列表(可选)
1
2
3
4
5
@array = qw{ pebbles dino fred barney betty};
@removed = splice @array, 1,2,qw(wilma); #删除dino fred,增wilma

@array = qw{ pebbles dino fred barney betty};
@removed = splice @array, 1,0,qw(wilma); #dino前增wilma

foreach 控制结构

控制变量($rock)每次迭代从列表中取一个新值;
控制变量不是元素拷贝而是元素本身;
如果循环中修改该变量,原始列表中的元素也会被修改。

reverse 操作

reverse(逆转)读取列表,按相反的顺序返回,不会修改传递进来的参数。

1
2
3
@barney = reverse (@fred); #得到10,9,8,7,6
reverse @fred; #错误,没有改变@fred 的值
@fred = reverse @fred; # 改变了@fred 的值

sort 操 作

sort 对列表操作,根据内部字符顺序进行排序,返回排序后的列表

1
2
3
sort @rocks; #错误,不会修改@rocks 
@rocks = sort @rocks; #现在@rocks 值是经过排序的
@numbers = sort 97..102; #得到100,101,102,97,98, 99

each 操作

调用each,返回数组元素对应的两个值

索引值和元素值

1
2
3
4
@rocks = qw(bedrock slate rubble granite);
while ( ( $index, $value ) = each @rocks){
print "$index: $value\n";
}

标量和列表上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
#返回数组元素的个数
@people = qw( fred barney betty );
$number = 42 + @people; #标量context:42+3,得到45


@backwards = reverse qw / yabba dabba doo /;
#返回doo, dabba, yabba
$backwards = reverse qw/ yabba dabba doo /;
#返回oodabbadabbay,每个单词单独逆序


@wilma = undef; #得到一个元素的列表(undef),不同于下面的例子
@betty = (); #将数组置空的正确方法

强制指定标量上下文

scalar:不是真正的函数,仅告诉Perl在这里提供标量

1
2
3
4
@rocks = qw(talc quartz jade obsidian);
print "How many rocks do you have?\n";
print "I have ", @rocks, "rocks!\n"; #错误,输出各种rocks 的名字
print "I have ", scalar @rocks, "rocks!\n"; #正确,输出其数字

子程序

定义一个子程序

定义是全局的

目前为止所出现的所有变量均是全局的;也就是说,它们在程序的任意部分都可以被访问

调用子程序

可以使用子程序的名字(带有&)来调用子程序

&marine;

返回值

子程序中最后计算的值

最后一个被求值的表达式,而非程序的最后一行

1
2
3
4
5
6
7
8
9
10
11
sub sum_of_fred_and_barney{ 
print "Hey, you called the sum_of_fred_and_barney subroutine!\n";
$fred + $barney; #返回值
}

sub sum_of_fred_and_barney{
print "Hey, you called the sum_of_fred_and_barney subroutine!\n";
$fred + $barney; #其值不会被返回
print"Hey, I"m returning a value now!\n"; #返回1
}

参数

  • 自动将参数列表存放在 @_ 数组
  • 第一个值存在$_[0],第二个存在​$_[1]
  • 与$_无关
  • 多余的参数被忽略;子程序不会使用​$_[2]
  • 参数不够时也会被忽略,默认得到undef
  • @_是子程序的一个私有变量

词法变量 my

1
2
3
4
5
6
7
#my操作符不会改变赋值时的上下文
my ($num) = @_; #列表context, 同($sum) = @_;
my $num = @_; #标量context,同$num = @_;

#my操作符不加括号时,只能声明单个词法变量
my $fred, $barney; #错误!没有定义$barney
my ($fred, $barney); #两个均定义了

use strict 编译指令

Perl 是一种宽容的语言。如希望Perl 严格一些可以使用use strict

1
use strict;

省略&

  • Perl 从语法中能知道这是一个子程序调用,或者如果编译器在调用之前知道此子程序的定义,则子程序前的符号&是可以省略的
  • 子程序与perl内部函数重名,必须使用&符号

非标量返回值

如在列表上下文中调用某个子程序,则其会返回列表值

持久性私有变量

state

操作符声明变量,作用域限定在子程序内部,但是多次调用子程序,期间会保留该变量的值

输入输出

写入文件

> 原有数据删除,写入新的数据
>> 不删除原有数据,添加到原数据结尾

split

数组=split(/分隔符/,标量);

来自钻石操作符的输入<>

1
2
3
4
5
6
7
8
9
10
11
12
#e:/perl aaa.txt bbb.txt ccc.txt
open(MYTEXT,"e:/perl");
while (defined($a=<>)){
chomp $a;
print $a;
}
#命令行输入E:\perl>perltest.pl aaa.txt bbb.txt ccc.txt
while(<>){
chomp;
print $_;
}

调用参数:**<>会首先查看@ARGV**数组,决定用哪些文件名

1
2
3
4
5
6
7
8
open(MYTEXT,"e:/perl");

@ARGV=qw(aaa.txt bbb.txt ccc.txt);
while (defined($a=<>)){
chomp $a;
print $a;
}

标量变量中的文件句柄

1
2
3
4
5
6
open ($bbb,"<","e:/perl/aaa.txt");
while (defined($a=<$bbb>)){
chomp $a;
print $a;
}

哈希

哈 希 赋 值

  1. 直接赋值: $hash{"key"}=value;

  2. 一般赋值 : %hash= ("key",value);

  3. 胖箭头赋值 %hash=("key"=>value);

展开哈希

@aaa=%home;

Reverse 哈希

%aaa=reverse %home;

Keys和values函数

返回

key set

value set

exists 函数

exists $home{'aaa'};

delete 函数

$remove=delete $home{"aaa"};

正则表达式

元字符

点号.:能匹配任意一个字符的通配符,换行符除外。有且仅有一个字符

简单的量词

  • 星号*:匹配它前面的内容零次或多次。

  • .*:匹配任意字符零次到无限次

  • 加号+:匹配它前面的内容一次或多次

  • 问号:它前面的内容出现一次或没有

模式分组(grouping)

反向引用 (back reference)与捕获组( capture group )

反向引用(back reference)是正则表达式内部的匹配变量,用于匹配之前( )分组中所匹配的文字。
写法为反斜线后面接数字,\1\2等。
相应的数字表示对应顺序的捕获组(capture group)

1
2
3
4
5
6
$_="okeyokey"; 
if (/(okey)\1/){
print "yes";
}
#yes,\1匹配的是okey

反向引用的分组:

从左到右查左括号,按照括号出现顺序以数字来命名。

反向引用 与捕获组的新写法

\1 == \g{1}; \2 == \g{2}...
倒数组: \g{-1}, \g{-2}... \g{-n}

择一匹配

1
2
3
4
5
" cab" =~ /a|b|c/                     # matches "c"
"cats and dogs" =~ /dog|cat|bird/; # matches "cat"
"cats" =~ /c|ca|cat|cats/; # matches "c"
"cats" =~ /cats|cat|ca|c/; # matches "cats"

字 符 集

[ ]:一组可能出现的字符,只匹配单个字符,方括号内的任意一个。

反义简写 [^ ]: 用于字符集开头,表示”非该字符集。”

字符集的简写

简写 含义
\d 一个数字
\w 一个字母、数字或下划线字符
\s 匹配一个空字符 [\n \t] 换页、制表、换行、回车、空格
\D 非数字 ^\d
\W ^\w
\S 非空白字符 ^\s
[\d\D] 任意字符

用正则表达式进行匹配

用m//进行匹配

1
2
3
4
5
6
7
8
$_ = "http://www.baidu.com";
if(/http:\/\/www.baidu.com/){
print "yes";
}
if(m!http://www.baidu.com!){
print "yes";
}#结果yes

绑定操作符 =~

默认$_

模式匹配修饰符

追加在模式表达式末尾定界符后面的字母

  • /a:按照ASCⅡ码范围匹配字符
  • /i:忽略大小写
  • /s:匹配任意字符(包括换行符)
  • /x:在模式中随意加入空白符 (\s , \t, \s*,\s+)或文字说明
1
2
3
4
5
$_="abc bcd edf"; 
if (/[A-Z]/i){
print "yes";
} #结果yes

组合选项修饰符:多项修饰符可连在一起,写在模式末尾,不区分顺序。如: / /six

锚位匹配修饰符

符号 说明
\A 绝对开头
\z 绝对末尾
\Z 匹配末尾,允许后边出现换行符
\b 匹配任何单词的首尾(不能大于)
\B 非单词锚位(不能小于等于)

捕 获 变 量

圆括号内匹配到的字符串,保存在$1$2等变量中

捕获变量的存续期:捕获变量存储到下次成功的匹配为止

不捕获模式 (?:)非捕获组没有$x值,$x的值被付给下一个捕获组

命名捕获:?<key> 存储到 $+{key} 中

1
2
3
4
5
$_="aaa or bbb"; 
if (/(?<str1>\w+) or (?<str2>\w+)/){
print "$+{str1} \n$+{str2}";
}

自动捕获变量:

  • $`:匹配之前的部分
  • $“:剩下的未匹配的部分
  • $&:匹配到的部分

通 用 量 词

/a{n,m}/:匹配a 出现 ≥n次, ≤m次

/a{n, }/:匹配a出现 ≥ n 次

优先级

  1. ():分组&捕获
  2. 量词:重复操作 a?, a*, a+, a{n,m}
  3. 锚位和序列: abc, ^,$, \A, \Z, \z
  4. 择一竖线 | : a|b|c
  5. 原子 单独的字符 字符集和数字等: a, [abc], \d, {g2}

用正则表达式处理文本

用s/ / /进行替换

返回值为替换次数

用/g进行全局替换 /g /gsix

1
2
3
4
5
$_="aaa bbb aaa"; 
if (s/aaa/ddd/){ print $_; }#只将第一组aaa替换成ddd
$_="aaa bbb aaa";
if (s/aaa/ddd/g){ print $_; }#将所有aaa都替换成ddd

大小写转换 \U \L \u \l \E

\E 终止

\u \l 仅限首字母

Split 函数

1
2
Split (/pattern/, $string, limit);

Join 函数

与split作用相反

1
2
$word=join(",",@word_1);

贪婪匹配

在量词后用?修饰该量词,使得该量词不进行贪婪匹配

跨行的模式匹配

  • 在只有一行时:^与\A等价,$与\Z等价,它们的用法可以互换。
  • \A:在多行匹配中,表示绝对开头。(字符串开头)
  • \z:在多行匹配中,表示绝对结尾。(字符串结尾)
  • ^:在多行匹配中,表示行首。
  • $:在多行匹配中,表示行尾。
  • 在多行匹配中,^和$需要同m修饰符组合使用 / /m

其它控制结构

unless

等于 if(! )

until

while(! )

裸块控制结构

临时变量

循环控制

last break

next continue

redo 再来一次

标记语句块

对外层循环进行控制

1
2
3
4
5
6
LABEL: while(){ 
foreach (){
last LABEL; #next LABEL; #redo LABEL;
}
}

条件语句

print \$a if $a==0; 但仍是先测试条件再执行!

循环语句

同理

文件测试

文件测试操作符

  • e:是否存在
  • M:返回文件最后一次修改到程序运行时的间隔天数。
  • A:返回文件最后一次被访问到程序运行时的间隔天数。
  • s:返回文件大小 单位是字节byte

虚拟文件句柄 _

栈式文件测试操作符

  • r
  • w

靠近文件名的先执行,从右往左执行,一般用于返回布尔值的文件测试中,其他返回值的容易出错

stat和lstat函数

获取文件的所有其他信息

localtime函数

gmtime: 取得当前世界标准(格林威治)时间

目录操作

在目录树中移动

chdir操作符可以改变当前的工作目录

文件名通配 glob操作符

my @flie=glob "*.txt";

my @flie=<*.txt *.pl>;

目录句柄

opendir 代替 open
readdir代替 readline #读的是目录文件名,非文件内容。
closedir 代替 close

一次删除多个文件

unlink :指定要删除的文件列表。
unlink glob "*";##一次删除多个文件

重命名文件

rename

目录操作

创建目录 :mkdir

删除空目录:rmdir

删除非空目录 先用unlink glob "*" 移除目录内所有文件

字符串与排序

用index查找字符串

index(原始字符串,子字符串,起始位置)

rindex 从字符串末尾开始找 同上

用substr操作子字符串

substr(原始字符串,起始位置,长度)功能:提取一定长度的字符串

起始位置为负数,则从字符串末尾进行操作

用sprintf格式化字符串

1
$aaa=sprintf "%.2f",2.49999;