perl语言入门第六版读书笔记
本文最后更新于:2025年11月19日 下午
perl语言入门第六版
简介
- 本书涵盖的最低版本5.8
- CPAN,perl综合典藏网,里面包含扩展,文档等
- perl解析器能一次完成编译和运行这两个动作。(注意是有先编译,即运行前就可以检查到整个代码的语法错误)
标量数据
- perl每个语句必须以分号;结束
- perl的数字可以通过下划线分割,方便理解
0x1234_2222_ffff - perl虽然都是浮点数,但是支持取模运算(%)
- 如果源代码中有ascii之外的字符,那么加上一行
use utf8;,让编译器正确解释你的代码。 - 单引号内除了反斜杠和自身,所有字符都代表它们自己,包块换行符
- 字符串的连接操作使用的
.号 - 字符串的重复操作使用的小写字母
x,"aaa" x 3重复aaa 3次。 - perl里面包含大量的默认行为,当发现程序不对时,可以打开警告
use warnings;,也可在命令行中添加-w选项。use warnings;说的更灵活,可以指定某几行代码警告。 - 标量的变量前缀为
$ - 字符串比较运算符使用的
eq,ne不等,lt小于操作符 - 字符串’0’非空,但是代表条件假。它是唯一的非空字符串假
<STDIN>获取用户输入chomp($text)去掉结尾的换行符,chomp($text=<STDIN>)- 要判断某个字符串是undef而不是空字符串,可使用defined函数,如果是undef,那么返回假
- print函数中内插变量时,如果变量后面紧跟字符,那么变量应使用形式
print "${var}a"形式,避免perl认为变量名包含后面紧跟的字符a
字符串
- 截取字符串函数substr
my $part = substr($string, $pos, $length);1
2# 截取开头4个字符,末尾两个字符,用..拼接起来。
print substr($_, 0, 4) . ".." . substr($_, -2, 2);
列表和数组
- 引用整个数组时,数组名前面添加
@符号。 - 数组下标从0开始,最后一个索引值为
$#array,取最后一个元素,可直接用$array[-1] - 可用两个点
..操作符产生一个整数列表,如1..100,只能递增。 - 可用
qw操作符,产生一个字符串列表,perl发明人可真懒 - pop读出数组最后一个元素并返回,push添加元素到最后
- shift,unshift操作最左边的元素,和pop,push类似
@removed = splice @array,idx,del_num,@insert_array, 移除idx开始的n个元素,并插入一个数组,返回移除的数组。后两个参数可选,默认移除从idx到最后的所有元素。print @array会将数组元素一个个打印出来,print "@array",会在数组元素中间加一个空格打印出来。1
2
3foreach $i (qw / aa bb cc /){
print "$i"
}- foreach的控制变量并没有复制数组里面的值,相当于引用。修改控制变量会直接修改到数组本身。
- foreach可以省略控制变量,会使用默认变量
$_ reverse返回一个持续相反的列表,并不改变原列表sort返回ascii序的列表,也不会改变原列表- 数组的名称在列表上下文,返回元素的列表。在标量的上下文,返回数组元素个数。
chomp(@lines = <STDIN>)读所有行,并移除换行符
子程序
- 不需要子程序事先声明,如果有两个同名子程序,后面的会覆盖前面的
- 所有子程序都有返回值,没有明确指定return的话,返回值就是最后一次运算结果的值
- perl自动将参数列表存在名为
@_的数组变量中,那么第一个参数为$_[0] - 默认perl的所有变量都是全局变量,创建私有变量要使用
my。 - my操作符后面不加括号,只能声明单个局部变量,加括号才能声明多个,实际上是声明的一个列表。
use strict让perl严格约束代码- 如果编译器在调用子程序时看到过子程序的定义,那么调用子程序的时候可以省略
&号,添加&也可以避免和perl内置函数同名的问题,&总是会调用自定义的子程序。 - 单写一个return不给任何参数,表明返回的空。对于标量上下文,就是undef,列表上下文就是空列表。
- 持久私有变量。类似于静态变量。state操作符声明,需要使用
use feature 'state'语句
输入输出
1 | |
- 建议用大写字母命名文件句柄
- 有6个特殊的文件句柄是perl保留的:STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT
- 可通过如下命令打开文件句柄
1 | |
- 二进制方式读写
binmode die "some error: $!";结束程序并打印东西,$!表示系统错误信息,类似strerror。- die会自动打印行号和文件名,如果不需要打印这个,那么只需在后面加一个换行符。
- warn函数差不多,只是不会终止程序运行。
- 5.10开始,可以用
use autodie;。它如果检查到系统调用级别的错误,就会自动die。相当于不用检查文件打开是否成功这类错误了。 - $0中保存了程序的名字
- 文件句柄的使用和之前用得STDIN差不多。
print LOG "xxxx",将字符串输出到LOG这个句柄里。 - 重新打开已经打开的句柄时,perl会自动关闭原来的句柄,比如可通过如下语句重定向错误输出到文件
1
open STDERR, ">>error.log"; - 5.10开始有一个say函数,和print差不多,只是自动加一个换行符。
ARGV相关
$ARGV表示参数命令行的文件中,当前正在处理的文件名@ARGV里面保存了命令行的参数列表,一般就是输入的文件名,在<>操作中,列表的元素会一个个移除ARGV表示<>当前正在处理的文件句柄。
哈希
键必须是唯一的字符串
访问hash的语法为
$hash{$key},大括号访问整个哈希,可以使用%作为前缀。哈希可以转换为列表。列表也可以赋值给hash。
%reverse_hash = reverse %any_hash可以建立一个反序的哈希,即key-value变为value-key。给hash赋值可以使用列表的形式:
%some_hash = ('key1', 22, 'key2', "333")。这种形式不方便看。可以使用胖箭头=>,对perl而言,它只是逗号的另一种写法,唯一的区别在于胖箭头左边的裸字都会加上引号。于是可以这样初始化hash:1
2
3
4
5
6
7
8my %some_hash = (
key1 => "1231",
key2 =>123,
key3 => { # hash嵌套
aaa => 222,
bbb=> 233,
}
);注意hash初始化使用的圆括号,嵌套时用大括号
访问hash元素的时候可以省略key的引号,
$hash{"aaa"}和$hash{aaa}同义。my @k = keys %hash,my @v = values %hash两个函数可用于提取所有key和valueeach函数变量hash
1
2
3while (($key, $value) = each %hash){
;
}echo会从hash中返回键值对,这是一个两个元素的列表。而赋值后得到的列表在标量上下文就是元素个数,为2。所以一直循环,知道取不出来值。
exists函数用户检查hash中是否存在某个键:if(exists $books{leon})delete $books{leon}函数用于删除某个键值对。hash元素可以内插,但是不支持内插整个hash。如果想要打印整个hash,可以先把hash赋值给列表,然后内插整个列表。
%ENV这个内置的hash存储了环境变量
漫游正则表达式王国
- 正则表达式和glob(shell的文件名匹配模式)不是同一个东西
- 捕获分组时,反向应用的方法是
\1,\2。如何知道是第一个还是第二个,从左到右数括号的序号即可。从perl 5.10开始支持\g{N}来表示是第几组,可以更方便,可以指定负数 - perl 5.10开始引入
\R能匹配任意一种换行符 - 反义简写,
\D非数字,\W非单词,\S非空白符
用正则表达式进行匹配
m/xxx/flag,如果以//作为定界符,那么m可以省略。当然为了方便可以用其他的定界符。flag有:1
2
3
4
5
6
7
8
9
10i -- 忽略大小写
m -- 多行匹配
s -- 匹配任意字符,默认情况下点号 . 无法匹配换行符,如果指定了这个就可以匹配了。
x -- 忽略正则表达式中的空白符,这样方便分割正则表达式,让正则表达式看起来更清晰(可以分行写,每行写注释)
p -- ^PREMATCH, ^MATCH, ^POSTMATCH变量使用
perl 5.14开始可以指定如果解释字符:
a -- ascii
u -- unicode
l -- 使用本地化的语言设置锚位,不匹配任何字符,但可以指定位置
1
2
3
4
5
6^ -- 行首
$ -- 行尾
\A -- 字符串的绝对开头,多行的情况下和^有一点区别,单行和^同义
\Z -- 字符串的绝对末尾
\b -- 单词边界
\B -- 非单词边界绑定操作符
=~,默认情况下,正则匹配$_变量,$var =~ /reg/可以使其匹配$var变量。正则表达式中可以内插变量。
如果正则表达式有括号,表示要捕获这个分组,但有时不想捕获,可以使用
(?:xxx),表示不捕获这个分组。命名捕获。perl 5.10开始,可以直接把捕获的分组存入内置的
%+这个hash变量中,(?<name>regex)。使用这个变量的方法为$+{name}使用命名捕获后,反向引用的语法也随之改变为
\g{label}自动捕获变量。perl会自动把匹配前,匹配,匹配后的三串字符串存入如下三个变量,perl 5.10后,使用
/pflags会将结果存入更容易记忆的几个变量。1
2
3
4$` --- ${^PREMATCH}
$& --- ${^MATCH}
$' --- ${^POSTMATCH}
# 后面的三个变量也好理解,外面的花括号围住表示其中是完整的变量名,变量名前面加^避免重复。
用正则表达式处理文本
s///进行替换,返回bool值,成功为真,否则为假/g全局替换同
m//一样,替换也可以使用不同的定界符,对于没有左右之分的字符,写三个就行,如果不是就需要成对写,如下几种意思一样:1
2
3
4s/123/456/
s|123|456|
s{123}{456}
s[123](456)和
m//一样,替换也可以使用绑定操作符$aa =~ s/123/456//r不直接操作源字符串,而是返回一个新的。my $copy = $orig =~ s/111/222/大小写转换
1
2
3
4\U -- 把之后的所有字符转为大写, s/aaa/\U$var/
\L -- 把后面的所有字符转为小写
\E -- 停止后面的字符转换
\u, \l -- 只转换一个字符上面的转换在print里面也是可以用得。
split /separator/, '$string'操作符。分割字符串,返回列表。默认以空白字符分割,默认操作$_变量。如果要在split的模式中使用分组,那么要使用分组不捕获写法
(?:)join aaa, @array,在字符串中加入粘合剂在列表上下文,使用
m//,匹配成功返回所有捕获分组的列表,失败返回空列表$^I = ".bak"变量,设置后,钻石操作符s///时,会直接写原文件,但会有一个备份文件生成。如果设置这个字符串为空串,那么不会生成备份文件。1
2
3
4
5$^I = ".bak";
while (<>){
s/aaa/bbb/g;
print;
}有时替换可以先使用占位符
\0,或者chomp后使用\n。
其他控制结构
表达式修饰符,即可以在一行里面写上if , foreach这种。使用foreach修饰符的时候无法自选控制变量,必须使用
$_print "ok" if $ok;foreach和for其实等价,如果括号内没有分号,那么是foreach循环,如果有分号那么是for循环。
last操作符等价于break
next操作符等价于continue
redo操作符合next相似,区别在于,next会继续下一次迭代,而redo会重新执行这次迭代
带标签的块,可以让里层直接跳到外层的某个循环点
定义或操作符
//,看着跟着注释符一样…。如果左侧的值未定义(undef),那么使用右侧的值,常用于赋默认值my $last_name = $last_name{$someone} // '(no last name)';
perl模块
1 | |
- 还有中面向对象的模块,使用的使用需要使用瘦箭头
->
DateTime模块
1 | |
Time::Piece模块
(5.10内置)
1 | |
安装模块
先在cpan网搜索自己需要什么模块,然后通过命令安装,
示例如下,第一次可能需要配置,自动即可
1 | |
文件测试
1 | |

