perl 读书笔记
时间:2010-09-19 来源:h_xin8211
####################
#
# 声明
#
####################
此文是学习Perl过程的笔记,当做小手册使用,方便查找。此文档更新至 2010.01.01
此文语法点及例程出处:
Perl语言入门(第五版) 小骆驼
Perl语言编程(第三版) 大骆驼
第三章 列表与数组
$fred[0]="yabba"
qw简写 qw(...)
pop 取出数组中最后一个元素
$fred = pop(@array)
pop @array
push 添加一个(或一串)元素到数组尾端
push(@array,0)
shift 取出数组中第一个元素
$m=shift(@array)
unshift 添加一个(或一串)元素到数组开始处
unshift(@array,5)
foreach 控制结构
foreach $rock (qw/ a b c /){
print "$rock";
}
reverse 按相反次序返回列表
@barney = reverse(@fred)
sort 根据ASCII码序排列
@sorted = sort(@rocks)
第四章 子程序
$_ 老地方
@_ 数组变量,存放子程序参数的数组,子程序专有变量
$n = &max(10,15); #此子程序有2 个参数
sub 定义子程序
&marine 调用子程序
use strict 严格规则的编译命令
return 从子程序中立即返回
4.5 私有变量
my 定义私有变量某个值
state 定义持久性私有变量
第五章 输入与输出
<STDIN> 读取标准输入
while(<STDIN>) 存储到变量里,每次读入一行
foreach(<STDIN>) 存储到数组里,每次读入所有文件
<> 读入程序后面的参数列表
@ARGV <>的输入参数列表
$_的值,从@ARGV中获得
./my_program fred - betty "-"表示从标准输入中获得
printf格式化输出
%d 十进制整数,舍去小数点之后的数字
%s 字符串,可设定宽度
printf "%10s\n","wilma" 右对齐
printf "%-15s\n","wilma" 左对齐
%f 转换浮点数,四舍五入,可指定小数点之后的输出位数
printf "%12f\n", 23;
printf "%12.3f\n",23;
printf "%12.0f\n",23;
5.6 句柄
perl自身有六个句柄:STDIN STDOUT STDERR DATA ARGV ARGVOUT
Larry推荐句柄全部大写
5.7
open 定义其它的文件jubing
open CONFIG, “dino”; # 打开一个CONFIG句柄,指向dino文件,从文件dino中读取数据。
open CONFIG, “<dino”; # 同上,指定了方向。
open BEDROCK, “>fred”;
open LOG,“>>logfile”;
open CONFIG, "<", "dino"; # 同上,指定了方向。
open BEDROCK, ">", "fred";
open LOG, ">>", "logfile";
select BEDROCK 选择文件句柄
close 关闭句柄
die函数将打印出你给它的消息
$! 仅对系统请求失败时,输出原因
say 输出变量值或字符串,并在后面自动加上换行符"\n"
第六章 哈希
$hash{$some_key}
%family_name 整个哈希
my &last_name = (
"fred" => "flintstone",
"dino" => undef,
"barney" => "rubble",
);
keys函数 返回键列表
values函数 返回值列表
如在标量上下文中,这两个函数都会返回哈希中 键/值对的个数
my $count = keys %hash # 得到 3
each函数 列出每个键/值对
exists函数 检查哈希中是否有某个键
if (exists $books{"dino"}){
print "Hey,there's a library card for dino!\n";
}
delete函数 从哈希表中删除指定的键及其相对应的值
第七章 正规表达式
/(.)\1/ 模式分组 反向引用
/((.)(.)\3\2)\1/ 分组按左边括号顺序来划分
在perl5.10中,添加反向引用格式\g{1}
/(.)\g{1}/
7.2
/abba/ = m!abba!
7.2.1
. 一次字符
.* n个字符
(|)
7.2.2 量词
* {0,}
+ {1,}
? {0,1}
7.3.1 字符类的简写
\d 数字 [0-9]
\w "word" [a-zA-Z0-9_]
\s 空白 [\f\t\n\r]
匹配完整单词 加“+”字符
\w+
perl5.10中增加简写
\h 匹配横向空白 [\t ]
\v 匹配纵向空格 [\f\n\r]
\R 匹配任何类型的断行
反义简写
[^\d] \D 非数字
[^\w] \W 非word
[^\s] \S 非空白
第八章 正规表达式的应用
8.1
/.../是m/.../模式匹配的简写
/abba/ m/abba/ # 分隔符可选
(abba)
!abba!
8.2 可选修饰符
/i 不区分大小写
/s 匹配任何字符,增加换行符"\n"
/x 模式里随意添加空格,以使更容易阅读
8.3 锚定
^ 开头匹配
$ 结尾匹配
\b 词界锚定
8.4 绑定操作符 =~
$some_other=~/\brub/
8.6 捕获变量
$_ = “Hello there, neighbor”;
if(/(\S+) (\S+), (\S+)/){
print “words were $1 $2 $3”;
}
不捕获模式(?:...) 告知perl这一对括号完全是为了分组而存在的
if(/(?:bronto)?saurus (steak|burger)/){
print "Fred wants a $1\n";
}
标签命名捕捉
(?<LABEL>PATTERN) 引用时用$+{LABEL}
反向引用也有新标识格式
\g{LABEL}
或
\k<LABEL>
8.6.2 自动匹配变量
%& 匹配部分
$` 匹配前部分
$' 匹配后部分
使用自动匹配变量,会使运行速度变慢,慎用
通用量词
a{3,15}
* {0,}
+ {1,}
? {0,1}
8.8 优先级
1. ()
2. 数量词 * + ?{1,9}
3. 锚定和序列
4. (|)
5. 元素 a [abc] \d \1
第九章 使用正规表达式处理文件
9.1
s///g 全局查询并替换
s#^https://#http://#; 分隔符可改
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;
9.1.3 修饰符
/i 不区分大小写
/s 匹配任何字符
/x 添加空格
9.1.4 绑定操作
$file_name =~ s#^.*###s; #将$file_name 中所有的Unix 类型的路径去掉
9.1.5 大小写转换
\U 转换后均为大写
\L 转换后均为小写
\E 不影响后续字符
s/ (\w+) with (\w+) /\U$2\E with $1/i;
\u 变大写,但只影响之后的第一个字符
\l 变小写,但只影响之后的第一个字符
s/(fred|barney)/\u$1/gi;
也可在双引号中使用
9.2 split 定义分隔符
它会根据分隔符才开一个字符串,只要你能将分隔符写成模式的正规表达式
格式:@fields = split /separator/, $string;
默认,开头的空元素会被返回,结尾的空元素被丢弃,-l参数可保留
默认,会以空白字符为分隔符,对$_进行分割
my @fields = split; 等效于 split /\s+/,$_;
9.3 join函数
join与split恰好相反,join会把这些片段联合成一个字符串
注意:join 的第一个参数是字符串,而非模式
用法:my $result = join $glue,@pieces;
my $x = join ":",4,6,8,10,12; 结果$x为“4:6:8:10:12”
列表上下文中的m//
在列表上下文中使用模式匹配符(m//)时,如果模式匹配成功,那么返回的是所有捕获变量的列表;如果匹配失败,则会返回空列表。
my($first,$second,$thind) = /(\S+) (\S+), (\S=)/;
匹配中有一对圆括号的模式,它会在每次匹配成功时返回一个捕获串
my @words = ($text =~ /([a-z]+)/ig)
在哈希上下文中
my %last_name = ($date =~ /(\w+)\s+(\w+)/g);
9.5.1 非贪婪的数量词
.+? 从头进行非贪婪匹配
.*?
{5,8}?
{8,}?
??
9.5.2 匹配多行文本
/m
锚定符由原来的整个文本范围,变为整行范围
9.5.3 更新大量文件
先打开一个新文件,然后把跟就文件相同的内容写进去,并且在需要的位置进行改写
#! /usr/bin/perl –w
use strict;
chomp(my $date = ‘date’);
$^I =“.bak”;
while(<>){
s/^Author:.*/Author: Randal L. Scharwartz/;
s/^Phone:.*\n//;
s/^Date:.*/Date: $date/;
print;
}
9.5.4 在命令行中进行修改
$perl –p –i.bak –w –e ‘s/Randall/Randal/g’fred*.dat
-0<数字>
(用8进制表示)指定记录分隔符($/变量),默认为换行
-00
段落模式,即以连续换行为分隔符
-0777
禁用分隔符,即将整个文件作为一个记录
-a
自动分隔模式,用空格分隔$_并保存到@F中。相当于@F = split ”。分隔符可以使用-F参数指定
-F
指定-a的分隔符,可以使用正则表达式
-e
执行指定的脚本。
-i<扩展名>
原地替换文件,并将旧文件用指定的扩展名备份。不指定扩展名则不备份。
-l
对输入内容自动chomp,对输出内容自动添加换行
-n
自动循环,相当于 while(<>) { 脚本; }
-p
自动循环+自动输出,相当于 while(<>) { 脚本; print; }
9.5.5 非捕捉用的括号
if(/(?:bronto)?saurus (steak|burger)/)
{
print “Fred wants a $1\n”;
}
第十章 更多控制结构
10.1 unless
# 条件为假时 执行
# 或用 ! 取反
if(! ($fred =~ /^[A-Z_]\w*$/i)){
print “The value of \$fred doesn’t look like a Perl identifier name.\n”;
}
10.2 until
# 直到条件为真时,停止。
# while的取反
10.3 条件修饰词
# 只有单个表达式,才允许这样写。
print “$n is a negative number.\n”if $n<0;
10.4 裸块控制结构
# 没有关键字或条件的块
# 因临时变量声明在最小范围里,放在裸块中,限制my 临时变量的作用范围
#不循环,只执行一次,是一个伪循环
{
print “Please enter a number:”;
chomp(my $n = <STDIN>);
my $root = sqrt $n; #计算平方根
print “The square root of $n is $root.\n”;
}
10.5 elsif
if(!defined $dino){
print “The value is undef.\n”;
}elsif($dino =~ /^-?\d+\.?$/){
print “The value is an integer.\n”;
}elsif($dino =~ /^-?\d*\.\d+$/){
print “The value is a _simple_ floating-point number.\n”;
}elsif($dino eq‘’){
print “The value is the empty string.\n”;
}else{
print “The value si the string ‘$dino’.\n”;
}
10.8 循环控制
last 立即结束
next 跳到下一循环
redo 回到此循环头部 在执行此循环
10.9
&& # 逻辑与 AND
|| # 逻辑或 OR
10.9.2 三元操作符 ?:
# 第一个表达式为真时,执行第二个表达式,为假时,执行第三个表达式。
Express ? if_true_expr : if_false_expr
my $size =
($width < 10)? "small" :
($width < 20)? "medium":
($width < 30)? "large" :
"extra-large";
perl5.010中的 "否定义" 操作符 "//"
use 5.010;
my $last_name = $last_name{$someone} // '(No last name)';
模块
perldoc CGI 查询模块
perl Makefile.PL 手动安装模块到系统目录
make install
perl Makefile.PL PREFIX=/Users/fred/lib 手动安装模块到指定的目录
perl Build.PL 用辅助模块 Module::Build来编译并安装
./Build install
有些模块有依赖关系,所以可以用自带的CPAN.pm来网络安装模块
perl -MCPAN -e shell
用cpan工具来网络安装模块
cpan Module::CoreList LWP CGI::Prototype
File::Basename模块
use File::Basename;
可选用模块中的部分函数列表
use File::Basename qw/basename/;
也可指定空函数列表
usr File::Basename qw//;
使用函数的模块全名来使用函数
my $dirname = File::Basename::dirname $name
文件测试
检测选项含义
-r 文件或目录对此(有效的)用户(effective user)或组是可读的
-w 文件或目录对此(有效的)用户或组是可写的
-x 文件或目录对此(有效的)用户或组是可执行的
-o 文件或目录由本(有效的)用户所有
-R 文件或目录对此用户(real user)或组是可读的
-W 文件或目录对此用户或组是可写的
-X 文件或目录对此用户或组是可执行的
-O 文件或目录由本用户所有
-e 文件或目录名存在
-z 文件存在,大小为0(目录恒为false)
-s 文件或目录存在,大小大于0(值为文件的大小,单位:字节)
-f 为普通文本
-d 为目录
-l 为符号链接
-S 为socket
-p 为管道(Entry is a named pipe(a“fifo”))
-b 为block-special 文件(如挂载磁盘)
-c 为character-special 文件(如I/O 设备)
-u setuid 的文件或目录
-g setgid 的文件或目录
-k File or directory has the sticky bit set
-t 文件句柄为TTY(系统函数isatty()的返回结果;不能对文件名使用这个测试)
-T 文件有些像“文本”文件
-B 文件有些像“二进制”文件
-M 修改的时间(单位:天)
-A 访问的时间(单位:天)
-C 索引节点修改时间(单位:天)
同一文件的多项属性测试
if(-r $file and -w $file){
...}
因要翻阅所有文件两次,非常耗资源,所以使用虚拟文件句柄"_" 它会公诉用上次查询或的文件信息来做当前的测试
if(-r $file and -w -){
...}
stat 和 lstat 函数
返回属性信息,包括文件连接数,拥有者ID,之类的13个数字元素列表。
localtime 函数
第十二章 目录操作
chdir "/etc"
12.2 globbing 文件名通配
echo "*.pm" -> shell
glob "*.pm" -> perl
glob "*" -> perl 不包括“.”
glob ".* *" -> perl 由点开头文件 和 不由点开头的所有文件
my @all_files=<*> # 同 @all_files=glob"*"
readline # 得到间接文件句柄读入操作
12.4 目录句柄
从目录里取得文件名列表,返回所有文件,包括"." ".." 等隐含文件
next if $name =~ /^\./; 排除以点号开头的字符串
next if $name eq "." or $name eq ".."; 排除当前目录和上级目录
opendir # 打开目录句柄
readdir # 读入目录中文件名
closedir # 关闭目录句柄
12.7 删除文件 unlink
unlink返回删除的文件个数
unlink不能删除目录
rm -> shell # rm *.o
unlink -> perl # unlink glob "*.o" 返回删除文件个数
rmdir # 删除目录
readlink 取得符号链接指向的位置
my $where = readlink "carroll";
my $perl = readlink "/usr/local/bin/perl";
重命名文件 rename
rename "old", "new";
12.9 连接和文件
link # ln 硬连接
symlink # ln -s 软连接
readlink "carroll" # 得到软连接的实体
12.10 创建和删除目录
mkdir "fred",0755 # 创建目录
rmdir "fred"; # 只能删除空目录,不能递归删除目录,需要File:Path模块的rmtree函数
my $temp_dir = "/tmp/scratch_$$"; # $$ 当前进程号
mkdir $temp_dir,0700 or die "cannot create $temp_dir:$!";
...
unlink glob "$temp_dir/* $temp_dir/.*"; #删除临时目录下的所有文件,包括隐含文件
rmdir $temp_dir
oct(0755) # 十进制转为八进制
12.11 改变权限
chmod 0755,"fred","barney" # 权限值为八进制
12.12 改变所有者
chown 1004,100,glob "*.o" # chown useID,groupID,filename
如不是ID指定,用名称指定属性
getpwnam函数 # 将用户名翻译成数字
getgrnam函数 # 将组名翻译成数字
12.13 改变时间戳 uptime
格式:utime 访问时间,修改时间,文件名
my $now = time;
my $ago = $now - 24*60*60
utime $now,$ago,glob"*"
第十三章 字符串和排序
13.1使用索引寻找子串
用法:$where = index($big,$small); # 在$big字符串里寻找$small字符串首次出现的地方那个
# 开头找到返回0,无法找到返回-1
用第三个参数来制定开始搜索的地方
my $stuff = "Howdy world!";
my #where1 = index($stuff, "w"); # $where1为 2
my #where2 = index($stuff, "w", $where1+1); # $where2为 6
my #where3 = index($stuff, "w", $where2+1); # $where3为 -1 (没找到)
rindex 搜索子串最后出现的位置
my $stuff = "Howdy world!";
my #where1 = rindex($stuff, "w"); # $where1为 5
my #where2 = rindex($stuff, "w", $where1+1); # $where2为 8
my #where3 = rindex($stuff, "w", $where2+1); # $where3为 -1 (没找到)
13.2 substr
substr($string,开始字符数,截取长度)
substr($string,开始字符数) # 开始到截止
substr($string,-3,2) # 从倒数第三个字符开始
index与substr协同工作
my $long = "some very very log string";
my $right = substr($long, index($long, "l")); # 取出以字符l的位置开头的子串
my $string = "Hello, word!";
substr($string,0,5) = "Goodbye"; # $string现在为 "Goodbye,world!"
substr($string, -20)=~ s/fred/barney/g; # 只会处理最后20个字符的匹配替换
substr 第四个参数,替换子串串
my $previous_value = substr($string, 0, 5, "Goodbye"); # 现在为 "Goodbye,world!"
用sprintf格式化数据
sprintf格式化后的字符存储在变量里
my $date_tay = sprintf
"%4d/%02d/%02d %2d:%02d:%02d",
$yr, $mo, $da, $h, $m, $s; # 2009/01/19 3:00:08
my $money = sprintf "%.2f", 2.49997; # 四舍五入 得到 2.5
逗号分隔数字,以便读取
sub big_money {
my $number = sprintf "%.2f", shift @_;
1 while $number =~ s/^(-?\d+)(\d\d\d)/$1,$2/;
$number =~ s/^(-?)/$1\$/;
$number;
}
13.4 高级排序
飞碟操作符
<=> # 数字的三向比较
cmp # 字符串的三向比较
$a <=> $b # 如$a在$b之前,返回-1 如$b在$a之前,返回1 如相等,返回0
内嵌的排序子程序
sub by_number{$a<=>$b}
my @numbers = sort {$a<=>$b} @some_numbers; # in line子程序
my @numbers = reverse sort {$a<=>$b} @some_numbers; # 反向,降序排列
或
my @numbers = sort {$b<=>$a} @some_numbers; # 反向,降序排列
哈希按值排序
sub by_score = {$score{$b} <=> $score{$a}}; # 按哈希值的降序排列,所以是 $b <=> $a
第十五章 智能匹配与given-when结构 (perl5.10中出现)
新的智能匹配操作符(~~)
1. 如果操作数看起来是数字,就按数字来比较大小。
2. 如果操作时看起来时字符串,就按字符串来比较。
3. 如某一段操作数是正规表达式,就当作模式匹配来执行。
4. 如果是数组,就一个个匹配数字里的值。
%a ~~ %b # 哈希的键是否一致
%a ~~ @b # 至少%a中的一个键在列表@b之中
%a ~~ /Fred/ # 至少一个键匹配给定的模式
$a ~~ 'Fred' # 哈希中某一指定键$a{Fred}是否存在
@a ~~ @b # 数组是否相同
@a ~~ /Fred/ # 有一个元素匹配给定的模式
@a ~~ 123 # 至少有一个元素转化为数字后是123
@a ~~ 'Fred' # 至少有一个元素转化字符串后是'Fred'
$name ~~ undef # $name确实尚未定义
$name ~~ /Fred/ # 模式匹配
123 ~~ '123.0' # 数字和字符串是否大小相等
'Fred'~~ 'Fred' # 字符串是否完全相等
123 ~~ 456 # 是否大小相等
1. 字符串
use 5.0.10;
print "I found Fred in the name!" if $name ~~ /Fred/;
2. 哈希键值
use 5.0.10;
print "I found a key matching 'Fred'" if %name ~~ /Fred/;
3. 数组
use 5.0.10;
print "The arrays have the same elements!"
if @names1 ~~ @names2;
given-when 控制语句
同 if-elsif-else 相仿,区别是given-when可以再满足某个条件的基础上,继续测试其他条件
use 5.0.10;
given( $ARGV[0]){
when( /fred/i ){say 'Name has fred in it'}
when( /^Fred/ ){say 'Name starts with Fred'}
when( 'Fred'){say 'Name is Fred'}
default {say "I don't see a Fred"}
}
多个项目的when匹配
use 5.0.10;
foreach my $name ( $names){
when( /fred/i ){say 'Name has fred in it'}
when( /^Fred/ ){say 'Name starts with Fred'}
when( 'Fred'){say 'Name is Fred'}
default {say "I don't see a Fred"}
}
第十六章 进程管理
system函数
启动子进程最简单的方法是用system函数,例如要从perl调用unix的date命令,用 system "date";
这会创建一个字进程来运行date命令
system 'ls -l $HOME';
或
system "ls -l \$HOME";
逻辑真假判断:
unix里: 0-真 非0-假
perl里: 0-假 非0-真
所以,在system里要先颠倒真假
unless (system 'date'){
# 返回 0 的话就代表执行成功,往下执行
print "we gave you a date, OK!\n";
}
最简单做法就是在system操作符之前加上逻辑反,感叹号"!"
!system "rm -fr files_to_delete" or die "something went wrong";
exec函数
同system函数相仿
exech函数导致perl进程自己去执行任务
环境变量
perl的环境变量存储在特殊的哈希 %ENV 中
%ENV会先从shell中继承环境变量
后续也可以修改
$ENV{'PATH'} = "/home/rootbeer/bin:$ENV{'PATH'}";
delete $ENV{'IFS'};
my $make_result = system "make";
用反引号捕获输出结果
my $now = `date`; # 捕获date输出
print "The time is now $now"; # 不需要换行符\n 因为date的输出已经包含了
如要去除\n, 用chown
chown(my $now = `date`;)
在列表上下文中使用反引号
my @who_lines = `who` # 可完整保存输出的格式
my $who_text = `who` # 输出保存在一个标量文本里
#
# 声明
#
####################
此文是学习Perl过程的笔记,当做小手册使用,方便查找。此文档更新至 2010.01.01
此文语法点及例程出处:
Perl语言入门(第五版) 小骆驼
Perl语言编程(第三版) 大骆驼
第三章 列表与数组
$fred[0]="yabba"
qw简写 qw(...)
pop 取出数组中最后一个元素
$fred = pop(@array)
pop @array
push 添加一个(或一串)元素到数组尾端
push(@array,0)
shift 取出数组中第一个元素
$m=shift(@array)
unshift 添加一个(或一串)元素到数组开始处
unshift(@array,5)
foreach 控制结构
foreach $rock (qw/ a b c /){
print "$rock";
}
reverse 按相反次序返回列表
@barney = reverse(@fred)
sort 根据ASCII码序排列
@sorted = sort(@rocks)
第四章 子程序
$_ 老地方
@_ 数组变量,存放子程序参数的数组,子程序专有变量
$n = &max(10,15); #此子程序有2 个参数
sub 定义子程序
&marine 调用子程序
use strict 严格规则的编译命令
return 从子程序中立即返回
4.5 私有变量
my 定义私有变量某个值
state 定义持久性私有变量
第五章 输入与输出
<STDIN> 读取标准输入
while(<STDIN>) 存储到变量里,每次读入一行
foreach(<STDIN>) 存储到数组里,每次读入所有文件
<> 读入程序后面的参数列表
@ARGV <>的输入参数列表
$_的值,从@ARGV中获得
./my_program fred - betty "-"表示从标准输入中获得
printf格式化输出
%d 十进制整数,舍去小数点之后的数字
%s 字符串,可设定宽度
printf "%10s\n","wilma" 右对齐
printf "%-15s\n","wilma" 左对齐
%f 转换浮点数,四舍五入,可指定小数点之后的输出位数
printf "%12f\n", 23;
printf "%12.3f\n",23;
printf "%12.0f\n",23;
5.6 句柄
perl自身有六个句柄:STDIN STDOUT STDERR DATA ARGV ARGVOUT
Larry推荐句柄全部大写
5.7
open 定义其它的文件jubing
open CONFIG, “dino”; # 打开一个CONFIG句柄,指向dino文件,从文件dino中读取数据。
open CONFIG, “<dino”; # 同上,指定了方向。
open BEDROCK, “>fred”;
open LOG,“>>logfile”;
open CONFIG, "<", "dino"; # 同上,指定了方向。
open BEDROCK, ">", "fred";
open LOG, ">>", "logfile";
select BEDROCK 选择文件句柄
close 关闭句柄
die函数将打印出你给它的消息
$! 仅对系统请求失败时,输出原因
say 输出变量值或字符串,并在后面自动加上换行符"\n"
第六章 哈希
$hash{$some_key}
%family_name 整个哈希
my &last_name = (
"fred" => "flintstone",
"dino" => undef,
"barney" => "rubble",
);
keys函数 返回键列表
values函数 返回值列表
如在标量上下文中,这两个函数都会返回哈希中 键/值对的个数
my $count = keys %hash # 得到 3
each函数 列出每个键/值对
exists函数 检查哈希中是否有某个键
if (exists $books{"dino"}){
print "Hey,there's a library card for dino!\n";
}
delete函数 从哈希表中删除指定的键及其相对应的值
第七章 正规表达式
/(.)\1/ 模式分组 反向引用
/((.)(.)\3\2)\1/ 分组按左边括号顺序来划分
在perl5.10中,添加反向引用格式\g{1}
/(.)\g{1}/
7.2
/abba/ = m!abba!
7.2.1
. 一次字符
.* n个字符
(|)
7.2.2 量词
* {0,}
+ {1,}
? {0,1}
7.3.1 字符类的简写
\d 数字 [0-9]
\w "word" [a-zA-Z0-9_]
\s 空白 [\f\t\n\r]
匹配完整单词 加“+”字符
\w+
perl5.10中增加简写
\h 匹配横向空白 [\t ]
\v 匹配纵向空格 [\f\n\r]
\R 匹配任何类型的断行
反义简写
[^\d] \D 非数字
[^\w] \W 非word
[^\s] \S 非空白
第八章 正规表达式的应用
8.1
/.../是m/.../模式匹配的简写
/abba/ m/abba/ # 分隔符可选
(abba)
!abba!
8.2 可选修饰符
/i 不区分大小写
/s 匹配任何字符,增加换行符"\n"
/x 模式里随意添加空格,以使更容易阅读
8.3 锚定
^ 开头匹配
$ 结尾匹配
\b 词界锚定
8.4 绑定操作符 =~
$some_other=~/\brub/
8.6 捕获变量
$_ = “Hello there, neighbor”;
if(/(\S+) (\S+), (\S+)/){
print “words were $1 $2 $3”;
}
不捕获模式(?:...) 告知perl这一对括号完全是为了分组而存在的
if(/(?:bronto)?saurus (steak|burger)/){
print "Fred wants a $1\n";
}
标签命名捕捉
(?<LABEL>PATTERN) 引用时用$+{LABEL}
反向引用也有新标识格式
\g{LABEL}
或
\k<LABEL>
8.6.2 自动匹配变量
%& 匹配部分
$` 匹配前部分
$' 匹配后部分
使用自动匹配变量,会使运行速度变慢,慎用
通用量词
a{3,15}
* {0,}
+ {1,}
? {0,1}
8.8 优先级
1. ()
2. 数量词 * + ?{1,9}
3. 锚定和序列
4. (|)
5. 元素 a [abc] \d \1
第九章 使用正规表达式处理文件
9.1
s///g 全局查询并替换
s#^https://#http://#; 分隔符可改
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;
9.1.3 修饰符
/i 不区分大小写
/s 匹配任何字符
/x 添加空格
9.1.4 绑定操作
$file_name =~ s#^.*###s; #将$file_name 中所有的Unix 类型的路径去掉
9.1.5 大小写转换
\U 转换后均为大写
\L 转换后均为小写
\E 不影响后续字符
s/ (\w+) with (\w+) /\U$2\E with $1/i;
\u 变大写,但只影响之后的第一个字符
\l 变小写,但只影响之后的第一个字符
s/(fred|barney)/\u$1/gi;
也可在双引号中使用
9.2 split 定义分隔符
它会根据分隔符才开一个字符串,只要你能将分隔符写成模式的正规表达式
格式:@fields = split /separator/, $string;
默认,开头的空元素会被返回,结尾的空元素被丢弃,-l参数可保留
默认,会以空白字符为分隔符,对$_进行分割
my @fields = split; 等效于 split /\s+/,$_;
9.3 join函数
join与split恰好相反,join会把这些片段联合成一个字符串
注意:join 的第一个参数是字符串,而非模式
用法:my $result = join $glue,@pieces;
my $x = join ":",4,6,8,10,12; 结果$x为“4:6:8:10:12”
列表上下文中的m//
在列表上下文中使用模式匹配符(m//)时,如果模式匹配成功,那么返回的是所有捕获变量的列表;如果匹配失败,则会返回空列表。
my($first,$second,$thind) = /(\S+) (\S+), (\S=)/;
匹配中有一对圆括号的模式,它会在每次匹配成功时返回一个捕获串
my @words = ($text =~ /([a-z]+)/ig)
在哈希上下文中
my %last_name = ($date =~ /(\w+)\s+(\w+)/g);
9.5.1 非贪婪的数量词
.+? 从头进行非贪婪匹配
.*?
{5,8}?
{8,}?
??
9.5.2 匹配多行文本
/m
锚定符由原来的整个文本范围,变为整行范围
9.5.3 更新大量文件
先打开一个新文件,然后把跟就文件相同的内容写进去,并且在需要的位置进行改写
#! /usr/bin/perl –w
use strict;
chomp(my $date = ‘date’);
$^I =“.bak”;
while(<>){
s/^Author:.*/Author: Randal L. Scharwartz/;
s/^Phone:.*\n//;
s/^Date:.*/Date: $date/;
print;
}
9.5.4 在命令行中进行修改
$perl –p –i.bak –w –e ‘s/Randall/Randal/g’fred*.dat
-0<数字>
(用8进制表示)指定记录分隔符($/变量),默认为换行
-00
段落模式,即以连续换行为分隔符
-0777
禁用分隔符,即将整个文件作为一个记录
-a
自动分隔模式,用空格分隔$_并保存到@F中。相当于@F = split ”。分隔符可以使用-F参数指定
-F
指定-a的分隔符,可以使用正则表达式
-e
执行指定的脚本。
-i<扩展名>
原地替换文件,并将旧文件用指定的扩展名备份。不指定扩展名则不备份。
-l
对输入内容自动chomp,对输出内容自动添加换行
-n
自动循环,相当于 while(<>) { 脚本; }
-p
自动循环+自动输出,相当于 while(<>) { 脚本; print; }
9.5.5 非捕捉用的括号
if(/(?:bronto)?saurus (steak|burger)/)
{
print “Fred wants a $1\n”;
}
第十章 更多控制结构
10.1 unless
# 条件为假时 执行
# 或用 ! 取反
if(! ($fred =~ /^[A-Z_]\w*$/i)){
print “The value of \$fred doesn’t look like a Perl identifier name.\n”;
}
10.2 until
# 直到条件为真时,停止。
# while的取反
10.3 条件修饰词
# 只有单个表达式,才允许这样写。
print “$n is a negative number.\n”if $n<0;
10.4 裸块控制结构
# 没有关键字或条件的块
# 因临时变量声明在最小范围里,放在裸块中,限制my 临时变量的作用范围
#不循环,只执行一次,是一个伪循环
{
print “Please enter a number:”;
chomp(my $n = <STDIN>);
my $root = sqrt $n; #计算平方根
print “The square root of $n is $root.\n”;
}
10.5 elsif
if(!defined $dino){
print “The value is undef.\n”;
}elsif($dino =~ /^-?\d+\.?$/){
print “The value is an integer.\n”;
}elsif($dino =~ /^-?\d*\.\d+$/){
print “The value is a _simple_ floating-point number.\n”;
}elsif($dino eq‘’){
print “The value is the empty string.\n”;
}else{
print “The value si the string ‘$dino’.\n”;
}
10.8 循环控制
last 立即结束
next 跳到下一循环
redo 回到此循环头部 在执行此循环
10.9
&& # 逻辑与 AND
|| # 逻辑或 OR
10.9.2 三元操作符 ?:
# 第一个表达式为真时,执行第二个表达式,为假时,执行第三个表达式。
Express ? if_true_expr : if_false_expr
my $size =
($width < 10)? "small" :
($width < 20)? "medium":
($width < 30)? "large" :
"extra-large";
perl5.010中的 "否定义" 操作符 "//"
use 5.010;
my $last_name = $last_name{$someone} // '(No last name)';
模块
perldoc CGI 查询模块
perl Makefile.PL 手动安装模块到系统目录
make install
perl Makefile.PL PREFIX=/Users/fred/lib 手动安装模块到指定的目录
perl Build.PL 用辅助模块 Module::Build来编译并安装
./Build install
有些模块有依赖关系,所以可以用自带的CPAN.pm来网络安装模块
perl -MCPAN -e shell
用cpan工具来网络安装模块
cpan Module::CoreList LWP CGI::Prototype
File::Basename模块
use File::Basename;
可选用模块中的部分函数列表
use File::Basename qw/basename/;
也可指定空函数列表
usr File::Basename qw//;
使用函数的模块全名来使用函数
my $dirname = File::Basename::dirname $name
文件测试
检测选项含义
-r 文件或目录对此(有效的)用户(effective user)或组是可读的
-w 文件或目录对此(有效的)用户或组是可写的
-x 文件或目录对此(有效的)用户或组是可执行的
-o 文件或目录由本(有效的)用户所有
-R 文件或目录对此用户(real user)或组是可读的
-W 文件或目录对此用户或组是可写的
-X 文件或目录对此用户或组是可执行的
-O 文件或目录由本用户所有
-e 文件或目录名存在
-z 文件存在,大小为0(目录恒为false)
-s 文件或目录存在,大小大于0(值为文件的大小,单位:字节)
-f 为普通文本
-d 为目录
-l 为符号链接
-S 为socket
-p 为管道(Entry is a named pipe(a“fifo”))
-b 为block-special 文件(如挂载磁盘)
-c 为character-special 文件(如I/O 设备)
-u setuid 的文件或目录
-g setgid 的文件或目录
-k File or directory has the sticky bit set
-t 文件句柄为TTY(系统函数isatty()的返回结果;不能对文件名使用这个测试)
-T 文件有些像“文本”文件
-B 文件有些像“二进制”文件
-M 修改的时间(单位:天)
-A 访问的时间(单位:天)
-C 索引节点修改时间(单位:天)
同一文件的多项属性测试
if(-r $file and -w $file){
...}
因要翻阅所有文件两次,非常耗资源,所以使用虚拟文件句柄"_" 它会公诉用上次查询或的文件信息来做当前的测试
if(-r $file and -w -){
...}
stat 和 lstat 函数
返回属性信息,包括文件连接数,拥有者ID,之类的13个数字元素列表。
localtime 函数
第十二章 目录操作
chdir "/etc"
12.2 globbing 文件名通配
echo "*.pm" -> shell
glob "*.pm" -> perl
glob "*" -> perl 不包括“.”
glob ".* *" -> perl 由点开头文件 和 不由点开头的所有文件
my @all_files=<*> # 同 @all_files=glob"*"
readline # 得到间接文件句柄读入操作
12.4 目录句柄
从目录里取得文件名列表,返回所有文件,包括"." ".." 等隐含文件
next if $name =~ /^\./; 排除以点号开头的字符串
next if $name eq "." or $name eq ".."; 排除当前目录和上级目录
opendir # 打开目录句柄
readdir # 读入目录中文件名
closedir # 关闭目录句柄
12.7 删除文件 unlink
unlink返回删除的文件个数
unlink不能删除目录
rm -> shell # rm *.o
unlink -> perl # unlink glob "*.o" 返回删除文件个数
rmdir # 删除目录
readlink 取得符号链接指向的位置
my $where = readlink "carroll";
my $perl = readlink "/usr/local/bin/perl";
重命名文件 rename
rename "old", "new";
12.9 连接和文件
link # ln 硬连接
symlink # ln -s 软连接
readlink "carroll" # 得到软连接的实体
12.10 创建和删除目录
mkdir "fred",0755 # 创建目录
rmdir "fred"; # 只能删除空目录,不能递归删除目录,需要File:Path模块的rmtree函数
my $temp_dir = "/tmp/scratch_$$"; # $$ 当前进程号
mkdir $temp_dir,0700 or die "cannot create $temp_dir:$!";
...
unlink glob "$temp_dir/* $temp_dir/.*"; #删除临时目录下的所有文件,包括隐含文件
rmdir $temp_dir
oct(0755) # 十进制转为八进制
12.11 改变权限
chmod 0755,"fred","barney" # 权限值为八进制
12.12 改变所有者
chown 1004,100,glob "*.o" # chown useID,groupID,filename
如不是ID指定,用名称指定属性
getpwnam函数 # 将用户名翻译成数字
getgrnam函数 # 将组名翻译成数字
12.13 改变时间戳 uptime
格式:utime 访问时间,修改时间,文件名
my $now = time;
my $ago = $now - 24*60*60
utime $now,$ago,glob"*"
第十三章 字符串和排序
13.1使用索引寻找子串
用法:$where = index($big,$small); # 在$big字符串里寻找$small字符串首次出现的地方那个
# 开头找到返回0,无法找到返回-1
用第三个参数来制定开始搜索的地方
my $stuff = "Howdy world!";
my #where1 = index($stuff, "w"); # $where1为 2
my #where2 = index($stuff, "w", $where1+1); # $where2为 6
my #where3 = index($stuff, "w", $where2+1); # $where3为 -1 (没找到)
rindex 搜索子串最后出现的位置
my $stuff = "Howdy world!";
my #where1 = rindex($stuff, "w"); # $where1为 5
my #where2 = rindex($stuff, "w", $where1+1); # $where2为 8
my #where3 = rindex($stuff, "w", $where2+1); # $where3为 -1 (没找到)
13.2 substr
substr($string,开始字符数,截取长度)
substr($string,开始字符数) # 开始到截止
substr($string,-3,2) # 从倒数第三个字符开始
index与substr协同工作
my $long = "some very very log string";
my $right = substr($long, index($long, "l")); # 取出以字符l的位置开头的子串
my $string = "Hello, word!";
substr($string,0,5) = "Goodbye"; # $string现在为 "Goodbye,world!"
substr($string, -20)=~ s/fred/barney/g; # 只会处理最后20个字符的匹配替换
substr 第四个参数,替换子串串
my $previous_value = substr($string, 0, 5, "Goodbye"); # 现在为 "Goodbye,world!"
用sprintf格式化数据
sprintf格式化后的字符存储在变量里
my $date_tay = sprintf
"%4d/%02d/%02d %2d:%02d:%02d",
$yr, $mo, $da, $h, $m, $s; # 2009/01/19 3:00:08
my $money = sprintf "%.2f", 2.49997; # 四舍五入 得到 2.5
逗号分隔数字,以便读取
sub big_money {
my $number = sprintf "%.2f", shift @_;
1 while $number =~ s/^(-?\d+)(\d\d\d)/$1,$2/;
$number =~ s/^(-?)/$1\$/;
$number;
}
13.4 高级排序
飞碟操作符
<=> # 数字的三向比较
cmp # 字符串的三向比较
$a <=> $b # 如$a在$b之前,返回-1 如$b在$a之前,返回1 如相等,返回0
内嵌的排序子程序
sub by_number{$a<=>$b}
my @numbers = sort {$a<=>$b} @some_numbers; # in line子程序
my @numbers = reverse sort {$a<=>$b} @some_numbers; # 反向,降序排列
或
my @numbers = sort {$b<=>$a} @some_numbers; # 反向,降序排列
哈希按值排序
sub by_score = {$score{$b} <=> $score{$a}}; # 按哈希值的降序排列,所以是 $b <=> $a
第十五章 智能匹配与given-when结构 (perl5.10中出现)
新的智能匹配操作符(~~)
1. 如果操作数看起来是数字,就按数字来比较大小。
2. 如果操作时看起来时字符串,就按字符串来比较。
3. 如某一段操作数是正规表达式,就当作模式匹配来执行。
4. 如果是数组,就一个个匹配数字里的值。
%a ~~ %b # 哈希的键是否一致
%a ~~ @b # 至少%a中的一个键在列表@b之中
%a ~~ /Fred/ # 至少一个键匹配给定的模式
$a ~~ 'Fred' # 哈希中某一指定键$a{Fred}是否存在
@a ~~ @b # 数组是否相同
@a ~~ /Fred/ # 有一个元素匹配给定的模式
@a ~~ 123 # 至少有一个元素转化为数字后是123
@a ~~ 'Fred' # 至少有一个元素转化字符串后是'Fred'
$name ~~ undef # $name确实尚未定义
$name ~~ /Fred/ # 模式匹配
123 ~~ '123.0' # 数字和字符串是否大小相等
'Fred'~~ 'Fred' # 字符串是否完全相等
123 ~~ 456 # 是否大小相等
1. 字符串
use 5.0.10;
print "I found Fred in the name!" if $name ~~ /Fred/;
2. 哈希键值
use 5.0.10;
print "I found a key matching 'Fred'" if %name ~~ /Fred/;
3. 数组
use 5.0.10;
print "The arrays have the same elements!"
if @names1 ~~ @names2;
given-when 控制语句
同 if-elsif-else 相仿,区别是given-when可以再满足某个条件的基础上,继续测试其他条件
use 5.0.10;
given( $ARGV[0]){
when( /fred/i ){say 'Name has fred in it'}
when( /^Fred/ ){say 'Name starts with Fred'}
when( 'Fred'){say 'Name is Fred'}
default {say "I don't see a Fred"}
}
多个项目的when匹配
use 5.0.10;
foreach my $name ( $names){
when( /fred/i ){say 'Name has fred in it'}
when( /^Fred/ ){say 'Name starts with Fred'}
when( 'Fred'){say 'Name is Fred'}
default {say "I don't see a Fred"}
}
第十六章 进程管理
system函数
启动子进程最简单的方法是用system函数,例如要从perl调用unix的date命令,用 system "date";
这会创建一个字进程来运行date命令
system 'ls -l $HOME';
或
system "ls -l \$HOME";
逻辑真假判断:
unix里: 0-真 非0-假
perl里: 0-假 非0-真
所以,在system里要先颠倒真假
unless (system 'date'){
# 返回 0 的话就代表执行成功,往下执行
print "we gave you a date, OK!\n";
}
最简单做法就是在system操作符之前加上逻辑反,感叹号"!"
!system "rm -fr files_to_delete" or die "something went wrong";
exec函数
同system函数相仿
exech函数导致perl进程自己去执行任务
环境变量
perl的环境变量存储在特殊的哈希 %ENV 中
%ENV会先从shell中继承环境变量
后续也可以修改
$ENV{'PATH'} = "/home/rootbeer/bin:$ENV{'PATH'}";
delete $ENV{'IFS'};
my $make_result = system "make";
用反引号捕获输出结果
my $now = `date`; # 捕获date输出
print "The time is now $now"; # 不需要换行符\n 因为date的输出已经包含了
如要去除\n, 用chown
chown(my $now = `date`;)
在列表上下文中使用反引号
my @who_lines = `who` # 可完整保存输出的格式
my $who_text = `who` # 输出保存在一个标量文本里
相关阅读 更多 +
排行榜 更多 +