温故知新
时间:2010-04-01 来源:bing_fox
1. 数字
.1 所有数字都是双精度浮点数;
.2 整数 61_298_040_283_768 与 61298040283768 相同
.3 进制
0377 #八进制数字377,等同于十进制数字255
0xff #十六进制数字FF,等同于十进制数字255
0b11111111 #等同于十进制数字255
#当非十进制数超过四位时可以_来区分
0x1377_0B77
0x50_65_72_7C
.4 操作符
+ - * /
% #取模
** #指数, 2**3 == 8 2. 字符串(从ASCII 32 到ASCII 126)
.1 可以操作二进制字符串,如图片
.2 单引号
#唯一的两个转义字符
\' #表示'
\\ #表示\
.3 双引号
#转义字符有效
\n, \t, \\, \' ..........
.4 字符串操作符
. #连接
x #重复 "a"x3 -> "aaa"; 4x5 -> "44444"; 5x4 -> "5555" 3. 数字与字符串转换
.1 原则: 依赖于操作符,按需转换;
.2 "0xff" #非十进制数字符串,将会被转成0,除非用oct()或hex()将其显示转换 4. 调试报错
.1 use diagnostics;
.2 use warnings; 5. 标量
.1 赋值
=
+=, .=, -=, *=, /=, %=, x=
.2 undef 没赋值的标量, defined($var)可判断$var是否是undef 6. 列表与数组
.1 区别
列表可以不是数组
数组一定有一个列表,数组是列表的名字
如:($fred, $barney, $dino) = (“flintstone”, “rubble”, undef); #与数组无关
.2 数组是动态变化的
最后一个值的索引: $#name; 更简单的作法是-1;即$name[$#name]与$name[-1]是相同的
数组元素个数:$#name+1;
.3 样式
(1,2,3) #含有1,2,3 的列表
(1,2,3,) #同上,最后一个逗号被忽略
() #空列表-0 个元素
(1..100) #包含100 个整数的列表
.4 范围操作符..
(1 ..5) #同(1,2,3,4,5)
(1.7..5.7) #同上— 最小值和最大值被转换成整数
(5 ..1) #空列表— ..中的左值应小于右值,否则为空
(0,2 .. 6,10,12)#同(0,2,3,4,5,6,10,12)
($m ..$n) #由$m 和$n 的值决定
(0 .. $#rocks) #上节中有$#rocks 的介绍
.5 qw
(“fred”, “barney”, “betty”, “wilma”, “dino”)
qw(fred barney betty wilma dino )
#二者相同,qw会忽略空格,制表符,和标量
.6 列表赋值
($fred, $barney, $dino) = (“flintstone”, “rubble”, undef);
($fred, $barney) = ($barney, $fred) #交换两个变量
($fred, $barney) = qw <flintstone rubble slate granite>; #两个值被忽略了
($wilma,$dino) = qw[flintstone]; #$dino 为undef
.7 数组赋值
@rocks = qw / bedrock slate lava /;
@tiny = (); #空表
@giant = 1..1e5; #包含100,000 个元素的表
@stuff = (@giant, undef, @giant); #包含200,001 个元素的表
#数组只能包含标量值,不能包含其它的数组
.8 数组操作
.1 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 被丢弃了)
#如果数组为空,那pop 什么也不做(因为没有元素可以移出),并返回undef
.2 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 shift 和unshift 操作
#unshift 和
shift 对一个数组的开头进行操作
.4 @的混乱
print "hello @arr"; #将数组元素以空格分隔列出
print "hello [email protected] @arr"; #结果可能不是预想
print "hello abc\@163.com @arr";#转义
print "hello ".'[email protected]'." @arr"; #单引号
.9 遍历
.1 foreach
@rocks = qw/ bedrock slate lava /;
foreach $rocks(@rocks){
$rock = “\t$rock”; #@rocks 的每一个元素前加入一个tab, 修改元素
$rock . = “\n”; #每一个元素后加一个换行符
}
.2 $_
@rocks = qw/ bedrock slate lava /;
foreach (@rocks){
$_ = “\t$rock”; #@rocks 的每一个元素前加入一个tab, 修改元素
$_ . = “\n”; #每一个元素后加一个换行符
}
.10 reverse反向
@fred = 6..10; #如果不喜欢只能从小到大
@barney = reverse (@fred); #得到10,9,8,7,6
reverse @fred; #错误,没有改变@fred 的值
@fred = reverse @fred; #改变了@fred 的值
.11 sort 排序
#按照ASCII码排序
sort @rocks; #错误,不会修改@rocks, 一定要接收其返回值,否则没意义
@rocks = sort @rocks; #现在@rocks 值是经过排序的
.12 置空数组
@wilma = undef; #OOPS!得到一个元素的列表(undef),不同于下面的例子
@betty = (); #将数组置空的正确方法
.13 强制数组成为标量
print “I have ”, scalar @rocks, “rocks!\n”; #正确,输出其数字, scalar 强制转换
1.4 特殊情况
@lines = <STDIN>; #读入所有的行, Linux Ctrl+D结束, Windows Ctrl+Z结束
chomp = (@lines); #去掉所有的换行符
chomp (@lines = <STDIN>); #读入所有的行,不包括换行符 7. 子函数
.1 一般形式
sub max{
my ($m, $n) = @_;
if($m > $n){
print $m;
}
else{
Print $n;
}
}
.2 参数的长度
#注意参数过长或者过短,甚至没有参数
sub max{
if(@_ < 2){}
}
my ($num) = @_; #列表context, 同($sum) = @_;参数赋值
my $num = @_; #标量context,同$num = @_;参数个数
.3 返回值
返回最后一个运算式结果
return #如果是最后一个计算式,那么这不是必须的,但更易读
.4 my
声明局部变量,开启
use strict; 来控制严格的语法
.5 调用&
最好全部使用&来调用
清楚知道子程序与内嵌函数不重名,则可以省略&
8. 输入/输出
.1 标准输入
chomp($line=<STDIN>) #同上,更常用的方法
while (defined($line = <STDIN>)) {
print “I saw $line”;
}
#以下两者的区别
#while循环多次读取
while(<STDIN>){
print “I saw $_”;
}
#foreach一次性读取全部,可能会倒置内在不够,如400M
foreach(<STDIN>){
print “I saw $_”;
}
.2 <>
#<>使用@ARGV列表,如果为空则使用标准输入,不为空则顺序执行
while (defined($line = <>)){
chomp($line);
print “It was &line that I saw!\n”;
}
while(<>){
chomp;
print “It was $_ that I saw!\n”;
}
.3 标准输出
print $var1, $var2;
.4 格式化输出
printf "hello %s!", $name;
#其他一些规则
%g #它将根据需要自动选用浮点数,整数,或者指数
%d #整数,去掉小数点后的部分
%2d #
%10s #printf “%10s\n”, “wilma”; #输出为:○○○○○wilma
%-10s #print “%-15s\n”, “flintstone”; #输出为flintstone○○○○
#%f要分小数点前后
printf “%12f\n”, 6*7 + 2/3; #输出为: ○○○42.666667
printf “%12.3f\n”, 6*7 + 2/3; #输出为: ○○○○○○42.667
printf “%12.0f\n”, 6*7 + 2/3; #输出为: ○○○○○○○○○○43
%% #输出为%
print “Monthly interest rate: %.2f%%\n”,5.25/12; #输出的值为0.44%
.5 文件句柄
.1 标准句柄
Perl 自身有六个文件句柄:STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT #可以用管道,重定向改变方向
###$0为程序本身
.2 自定义文件句柄
open CONFIG, “dino”;
open CONFIG, “<dino”;
open BEDROCK, “>fred”;
open LOG,“>>logfile”;
.3 使用文件句柄
#读取
<MYFILE>与<STDIN>一模一样
#写入
print LOG “Captain’s log, stardate 3.14159\n”; #输出到LOG 中
printf STDERR “%D percent complete.\n”, $done/$total * 100;
###文件句柄和要打印的内容之间没有逗号
#改变默认的文件句柄, 不是一个好主意
select LOG;
$| = 1; #don’t keep LOG entries sitting in the buffer 9. 哈希hash
.1 why
机器更擅长处理数字,但对人而言,名字更容易记忆
.2 keys/values
keys 和values 均为任意的标量,key 可以是任意的表达式,但keys 通常转换为字符串,将表达式50/20 作为keys则其通常被转换为3
字符的字符串“2.5”
keys 是唯一的,但values 可以重复。
.3 存取
$hash{$some_key},访问不存在的hash 元素得到undef
$hash{$some_key} = $value;
%some_hash = (“foo”, 35, “bar”, 12.4, 2.5, “hello”, “wilma”, 1.72e30, “betty”, “bye\n”); #列表需要是偶数
%new_hash = %old_hash; #拷贝,很少用,浪费资源
#更明确的赋值
my %last_name = (
“fred” => “flintstone”,
“dino” => undef,
“barney”=> “rubble”;
“betty”=> “rubble”,
);
.4 hash函数
.1 keys, values
keys #返回全部key列表
values #返回全部value列表
#例子
my %hash = (“a”=>1, “b”=>2, “c”=>3);
my @k = keys %hash;
my@v = values %hash;
.2 each
while (($key, $value) = each %hash){
print “$key => $value\n”;
}
#返回key/value顺序是混乱的
.3 foreach
#先排序,后输出
foreach $key (sort keys %hash){
$value =$hass{$key};
print “$key => $value\n”;
#也可以不使用额外的临时变量$value
#print “$key => $hash{key}\n”;
}
.4 exists
#查看相应的key是否存在,value是否为空不重要
if(exists $books{$dino}){
print “Hey, there’s a libaray card for dino!\n”;
}
.5 delete
#删除元素对
delete $books{$person}; #将$person 的借书卡删除掉
.6 整个hash不可内插入字符串
10. 正则表达式
.1 what
匹配模式
.2 最简单的匹配
$_ =“yabba dabba doo”;
if(/abba/){
print “It matched!\n”;
}
.3 元字符
. #任意一个字符,(不包括换行符)
\ #转义
() #分组
| #选择符, or
.4 数量词
* #前面项,重复任意次
.* #叫做“任意字符串匹配模式”(不包括换行符)
+ #前面项,一个或多个
? #前面项,0个或一个
.5 字符类
[] #列表,匹配一个字符,只要列表中有的,[a-zA-Z]范围,[\000-\177]ASKII码,[^def]取反
\d 任何数字的类,[0-9]
\w 被称作“word’字符:[A-Za-z0-9_]。如果你的“words”由通常的字母,数字,下划线组成,那你将非常喜欢它,记住它只匹配一个字符
\s 对于匹配空白,于[\f\t\n\r ] #\s*将匹配任何个数的空白,\s+匹配一个以上的空白
[^\d], [^\w], 和[^\s] #补集, 也可以用\D, \W, \S
[\d\D] #匹配任何一个字符,包括换行符
11. 正则表达式应用
.1 符号
/fred/ #m/fred/的简写,m(fred), m<fred>, m{fred}, m[fred],或者m%fred%, m!fred!, m^fred^都可以
.2 修饰符
#改变默认行为
/yes/i #大小写无关
/ye.s/s #让.可以匹配换行符
/ye s/x #模式中可以添加空白,更易读,匹配时忽略掉.\s(\s*或\s+)来匹配空白
#/x还可以添加注释
/
-? #可选的负号
\d+ #小数点前一个或多个十进制数字
\.? #可选的小数点
\d* #小数点后一些可选的十进制数字
/x #模式结束
#多个修饰符连接使用,不分先后
.3 锚定
#限制搜索位置
^ #开头
$ #结尾 /^fred$/能同时匹配上“fred”和“fred\n”, /^\s*$/,它将匹配一个空行(blank line)
/\bfred\b/可以匹配上单词fred,但不能匹配frederick #词匹配,匹配\w那样的词
\B #\b的补集,注意要分开头与结尾
.4 绑定操作符,=~
#改变正则表达式操作的默认对象$_,而成为=~左边的标量,其优先级较高
my $some_other = “I dream of betty rubble.”;
if($some_other =~ /\brub/){
print “Aye, there’s the rub.\n”;
}
.5 内插
/($reg)/ #将模式部分以变量形式传递,但要注意可能$reg=dsf(sdkf的形式使程序不能工作
.6 匹配变量
$_ = “Hello there, neighbor”;
if(/\s(\w+),/){ #空格和逗号之间的词
print “the word was $1\n”; #the word was there
} #$1,$2,$3对应着相应序号的()匹配的内容
#匹配变量是易失的,第二次匹配时会覆盖第一次的结果;匹配不上时是undef,因此要及时使用或将其转移到普通标量内
.7 古怪而有用的变量
三个变量名为:
$& #整个被匹配的部分
$` #匹配的前一部分`
$' #匹配的后一部分
.8 一般数量词
/a{5,15}/将匹配5 个到15 个a 中的任意一个(包括5,和15)
星号(*)等同于{0,},表示0 个或多个。加号(+)等同于{1,},表示1 个或多个。而问号(?)则等同于{0,1}。
.9 优先级
#要注意优先及,()->数量词->锚定->最低的|
.10 测试程序
#检查你的正则表达式是否正常工作
#! /usr/bin/perl
while(<>){ #一次取一行输入
chomp;
if(/YOUR_PARTTEN_GOES_HERE/){
print “Matched: |$`<$&>$’|\n”; #特殊的变量`
}else{
print “no match: |$_|\n”;
}
}
12. 正则表达式处理文件
.1 替换 s/
# 返回bool值
$_ =“green scaly dinosaur”;
s/(\w+) (\w+)/$2, $1/; #现在为“scaly, green dinosaur”;
s/^/huge, /; #现在为“huge, scaly, green dinosaur”
s/,.*een//; #空替换,现在为“huge dinosaur”
s/green/red/; #匹配失败,仍然为“huge dinosaur”
s/\w+$/($`!)$& /; #现在为“huge (huge !)dinosaur”
s//\s+(!\W+)/$1 /; #现在为“huge (huge!) dinosaur”
s/huge/gigantic/; #现在为“gigantic (huge!) dinosaur”
s/sdfk/aaa/g #/g全部替换
#还可以使用还可以使用/i, /x, 和/s修饰符
.2 分隔符
#不一不定必须使用//
s#^https://#http://#;
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;
.3 绑定
$file_name =~ s#^.*###s; #将$file_name 中所有的Unix 类型的路径去掉, 原字符串会变化
.4 大小写
\U #之后的所有字母大写
\u #下一个字母大写
\L #之后的所有字母小写
\l #之后的一个字母小写
\E #截断影响
\u\L或\L\u #首字母大写,其余小写
.5 split与join
@fields = split /:/, “abc:def:g:h”; #返回(“abc”, “def”, “g”, “h”)
#以空白分割
my $some_input = “This is a \t test.\n”;
my @args = split /\s+/, $some_input; #(“This”, “is”, “a”, “test.”)
#相反的操作
my $x = join“:”, 4, 6, 8, 10, 12; #$x 为“4:6:8:10:12”
.6 用匹配赋值
$_ =“Hello there, neighbor!”;
my($first, $second, $third) =/(\S+) (\S+), (\S+)/;
my $text = “Fred dropped a 5 ton granite block on Mr. Slate”;
my @words = ($text =~ /([a-z]+)/ig);
my $data = “Barney Rubble Fred FlintstoneWilma Flintstone”;
my %last_name = ($data =~ / (\w+)\S+(\w+)/g);
.7 非贪婪的数量词
+?, *?, ??, {x, y}? #只要满足少的匹配即可,先少后多
.8 对多行字符串匹配
#/m
$_ =“I’am much better\nthan Barney is\nat bowling,\nWilma,\n”;
print “Found ‘wilma’at start of line\n”if /^wilma\b/im;
9. 替换多个文件
chomp(my $date = ‘date’);
$^I =“.bak”; #设置备份文件后缀名,.bak文件保持文件的原始状态
while(<>){
s/^Author:.*/Author: Randal L. Scharwartz/;
s/^Phone:.*\n//;
s/^Date:.*/Date: $date/;
print;
} 13. 其他控制
.1 unless
if 控制结构中,只有条件为真时,才执行块中的代码。如果你想在条件为假时执行,可以使用unless,也可以有else
.2 希望将while 循环的条件部分取反。此时,可以使用until
.3 表达式修饰符
print “$n is a negative number.\n”if $n<0; #显得非常紧凑
.4 裸块
#主要目的是提供变量小的作用域
{
body;
}
.5 elsif 语句
#Perl 没有像C 语言“switch”结构中的“fall-through(直接跳入)”下一个代码块的功能
.6 自增和自减
$m++与++$m的区别
.7 for
#同C语言
#for 与 foreach的关系
.8 循环控制
last 会立刻结束循环。(这同C 语言或其它语言中的“break”语句类似)
next 之后,又会进入下一轮循环(这和C 或者类似语言的“continue”相似)
redo。它会调到当前循环块的顶端,不进行条件表达式判断以及接着本次循环
,当Perl 遇见其中之一时,和遇见另一个是一样的。Perl 通过括号能理解你的目的。
.9 标签
LINE: #一般大写,以与函数名区分
last LINE; next LINE; redo LINE; #非常像goto
.10 短路操作
my $last_name = $last_name{$someone} ||‘(No last name)’;
.11 三元操作符?:
像if-then-else 一样
my $size =
($width < 10 ) ? “small”:
($width < 20) ? “medium”:
($width < 50) ? “large”:“extra_large”; #default
#1,100随机数int(1+ rand 100); 14. 文件检验
.1 判断标识符图表
.2 stat and lstat
#stat返回文件的全部属性
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blockes)
= stat($filename);
#lstat是针对链接文件的
.3 localtime
#将时间民戳转成一些有用日期时间变量
.4 位操作
&
|
^
>>
<<
~
.5 位串
"\xAA" | "\x55" #结果是\xFF, 位串可以无限长
.6 _ 文件句柄
#对_文件进行检验时,不进行新的操作,而是从缓存中直接读取上一次的结果
my($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime $timestamp; 15. 目录操作
.1 移动
chdir “/etc”or die “cannot chdir to /etc: $!”; #错误发生时将给变量$!赋值。通常应当检查$!的值
.2 展开文件名匹配
my @all_files = glob “*”;
my @pm_files = glob “*.pm”;
#my@all_files = <*>; ##基本上同@all_files = glob “*”一样;
.3 目录句柄
opendir DH, $dir_to_process or die “Cannot open $dir_to_process: $!”;
foreach $file(readdir DH) {
print “one file in $dir_to_process is $file\n”;
}
closedir DH;
.4 路径
#readdir返回值不包括路径
opendir SOMEDIR, $dirname or die “Cannot open $dirname: $!”;
while (my $name = readdir SOMEDIR) {
next if $name =~ /^\./; #跳过点文件
$name = “$dirname/$name”; #加上目录名
next unless–f $name and –r name; #除非是可读文件
}
.5 递归目录列表
File::Find #这个库可以做到
.6 删除文件
foreach my $file (qw(slate bedrock lava)) {
unlink $file or warn “failed on $file: $!\n”;
}
.7 重命名
rename “over_there/some/place/some_file”, “some_file”;
#批量改名
foreach my $file (glob “*.old”){
my $newfile = $file;
$newfile =~ s/\ .old$/.new/;
if (-e $newfile){
warn“can’t rename $file to $newfile: $newfile exists\n”;
}elsif(rename $file, $newfile){
##成功,什么也不做
} else {
warn “rename $file to $newfile failed: $!\n”;
}
}
.8 链接文件
link“chicken”, “egg” or warn “Can’t link chicken to egg: $!”; #硬连接
symlink “dodgson”, “carroll” or warn “Can’t sysmlink Dodgson to carroll: $!” #软连接
my $where = readlink “carroll”; #得到“dodgson”
my $perl = readlink“/usr/local/bin/perl”#可能得到Perl 放置的地方
unlink linkfile #删除
.9 创建和删除目录
mkdir “fred”, 0755 or warn “Cannot make fred directory: $!”;
#从命令行获取参数
my ($name, $perm) = @ARGV; #前面两个参数是名字和权限
mkdir $name, oct($perm) or die “cannot create $name: $!”; #oct将字符串当成八进制数
#删除目录
File::Path #可以自己写,但最好参数这个库
.10 修改权限
chmod 0755, “fred”, “barney”
.11 改变所有者
my $user = 1004;
my $group = 100;
chown $user, $group, glob “*.o”;
.12 改变时间戳
my $now = time;
my $ago = $now -24*60*60; #一天的秒数
utime $now, $ago, glob “*”; #设成当前访问的,一天之前修改的
16. 字符串和排序
.1 使用索引寻找子串
index("string here!", "her");
.2 substr 操作子串
substr("abc def ghi jkm", 2); #从index 2(这里是c)开始到结尾的子串
substr("abc def ghi jkm", 2, 5); #从index 2(这里是c)开始,截<=5个字符
substr("abc def ghi jkm", -2, 5); #从后向前的index 2(这里是j),截<=5个字符
.3 sprintf
与printf一样,只是不打印出来,而是存储在返回值中
.4 高级排序
sort sub_sort_func @arr; #用户自定义sub_sort_func来对@arr排序
#sub_sort_func的样子
sub sub_sort_func{
$a<=>$b;
}
#$a,$b为系统默认,返回值可能有三个,意思是
sub sub_sort_func {
if($a < $b){-1} elsif($a > $b){1} else {0}
}
#更长见的是$a <=> $b #针对数字; $a cmp $b #针对字符
my @numbers = sort { $a <=> $b } @some_numbers;
my @descending = reverse sort { $a <=> $b } @some_numbers; #反向,或者
my @numbers = sort { $b <=> $a } @some_numbers;
#对Hash排序
my %score = (“barney”=> 50, “fred”=> 205, “dino”=> 30);
my @winners = sort by_score keys %score;
sub by_score {
$score{$b} <=> $score{$a} #按照降序的成绩
or
$a cmp $b; #字母顺序的名字
}
#更夸张的5级排序
@patrons_IDs = sort {
&fines($b) <=> &fines($a) or
$items{$b} <=> $items{$a} or
$family_name{$a} cmp $family_name{$a} or
$personal_name{$a} cmp $family_name{$b} or
$a <=> $b
}
@patron_IDs;
17. 模块的使用
.1 查找
http://search.cpan.org/
.2 判断是否安装过
$perldoc CGI #看有没有CGI的文档
.3 避免冲突
use File:Basename qw/ /; #没有引入函数
my $dirname = File::Basename::dirname $name; #使用模块中的dirname,用全名
use CGI qw(:all); #加载全部函数
.4 DBI模块
use DBI;
$dbh = DBI->connect($data_source, $username, $password);
$sth = $dbh->prepare(“SELECT * FROM fooWHERE bla”);
$sth->execute();
@row_ary = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect();
.1 所有数字都是双精度浮点数;
.2 整数 61_298_040_283_768 与 61298040283768 相同
.3 进制
0377 #八进制数字377,等同于十进制数字255
0xff #十六进制数字FF,等同于十进制数字255
0b11111111 #等同于十进制数字255
#当非十进制数超过四位时可以_来区分
0x1377_0B77
0x50_65_72_7C
.4 操作符
+ - * /
% #取模
** #指数, 2**3 == 8 2. 字符串(从ASCII 32 到ASCII 126)
.1 可以操作二进制字符串,如图片
.2 单引号
#唯一的两个转义字符
\' #表示'
\\ #表示\
.3 双引号
#转义字符有效
\n, \t, \\, \' ..........
.4 字符串操作符
. #连接
x #重复 "a"x3 -> "aaa"; 4x5 -> "44444"; 5x4 -> "5555" 3. 数字与字符串转换
.1 原则: 依赖于操作符,按需转换;
.2 "0xff" #非十进制数字符串,将会被转成0,除非用oct()或hex()将其显示转换 4. 调试报错
.1 use diagnostics;
.2 use warnings; 5. 标量
.1 赋值
=
+=, .=, -=, *=, /=, %=, x=
.2 undef 没赋值的标量, defined($var)可判断$var是否是undef 6. 列表与数组
.1 区别
列表可以不是数组
数组一定有一个列表,数组是列表的名字
如:($fred, $barney, $dino) = (“flintstone”, “rubble”, undef); #与数组无关
.2 数组是动态变化的
最后一个值的索引: $#name; 更简单的作法是-1;即$name[$#name]与$name[-1]是相同的
数组元素个数:$#name+1;
.3 样式
(1,2,3) #含有1,2,3 的列表
(1,2,3,) #同上,最后一个逗号被忽略
() #空列表-0 个元素
(1..100) #包含100 个整数的列表
.4 范围操作符..
(1 ..5) #同(1,2,3,4,5)
(1.7..5.7) #同上— 最小值和最大值被转换成整数
(5 ..1) #空列表— ..中的左值应小于右值,否则为空
(0,2 .. 6,10,12)#同(0,2,3,4,5,6,10,12)
($m ..$n) #由$m 和$n 的值决定
(0 .. $#rocks) #上节中有$#rocks 的介绍
.5 qw
(“fred”, “barney”, “betty”, “wilma”, “dino”)
qw(fred barney betty wilma dino )
#二者相同,qw会忽略空格,制表符,和标量
.6 列表赋值
($fred, $barney, $dino) = (“flintstone”, “rubble”, undef);
($fred, $barney) = ($barney, $fred) #交换两个变量
($fred, $barney) = qw <flintstone rubble slate granite>; #两个值被忽略了
($wilma,$dino) = qw[flintstone]; #$dino 为undef
.7 数组赋值
@rocks = qw / bedrock slate lava /;
@tiny = (); #空表
@giant = 1..1e5; #包含100,000 个元素的表
@stuff = (@giant, undef, @giant); #包含200,001 个元素的表
#数组只能包含标量值,不能包含其它的数组
.8 数组操作
.1 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 被丢弃了)
#如果数组为空,那pop 什么也不做(因为没有元素可以移出),并返回undef
.2 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 shift 和unshift 操作
#unshift 和
shift 对一个数组的开头进行操作
.4 @的混乱
print "hello @arr"; #将数组元素以空格分隔列出
print "hello [email protected] @arr"; #结果可能不是预想
print "hello abc\@163.com @arr";#转义
print "hello ".'[email protected]'." @arr"; #单引号
.9 遍历
.1 foreach
@rocks = qw/ bedrock slate lava /;
foreach $rocks(@rocks){
$rock = “\t$rock”; #@rocks 的每一个元素前加入一个tab, 修改元素
$rock . = “\n”; #每一个元素后加一个换行符
}
.2 $_
@rocks = qw/ bedrock slate lava /;
foreach (@rocks){
$_ = “\t$rock”; #@rocks 的每一个元素前加入一个tab, 修改元素
$_ . = “\n”; #每一个元素后加一个换行符
}
.10 reverse反向
@fred = 6..10; #如果不喜欢只能从小到大
@barney = reverse (@fred); #得到10,9,8,7,6
reverse @fred; #错误,没有改变@fred 的值
@fred = reverse @fred; #改变了@fred 的值
.11 sort 排序
#按照ASCII码排序
sort @rocks; #错误,不会修改@rocks, 一定要接收其返回值,否则没意义
@rocks = sort @rocks; #现在@rocks 值是经过排序的
.12 置空数组
@wilma = undef; #OOPS!得到一个元素的列表(undef),不同于下面的例子
@betty = (); #将数组置空的正确方法
.13 强制数组成为标量
print “I have ”, scalar @rocks, “rocks!\n”; #正确,输出其数字, scalar 强制转换
1.4 特殊情况
@lines = <STDIN>; #读入所有的行, Linux Ctrl+D结束, Windows Ctrl+Z结束
chomp = (@lines); #去掉所有的换行符
chomp (@lines = <STDIN>); #读入所有的行,不包括换行符 7. 子函数
.1 一般形式
sub max{
my ($m, $n) = @_;
if($m > $n){
print $m;
}
else{
Print $n;
}
}
.2 参数的长度
#注意参数过长或者过短,甚至没有参数
sub max{
if(@_ < 2){}
}
my ($num) = @_; #列表context, 同($sum) = @_;参数赋值
my $num = @_; #标量context,同$num = @_;参数个数
.3 返回值
返回最后一个运算式结果
return #如果是最后一个计算式,那么这不是必须的,但更易读
.4 my
声明局部变量,开启
use strict; 来控制严格的语法
.5 调用&
最好全部使用&来调用
清楚知道子程序与内嵌函数不重名,则可以省略&
8. 输入/输出
.1 标准输入
chomp($line=<STDIN>) #同上,更常用的方法
while (defined($line = <STDIN>)) {
print “I saw $line”;
}
#以下两者的区别
#while循环多次读取
while(<STDIN>){
print “I saw $_”;
}
#foreach一次性读取全部,可能会倒置内在不够,如400M
foreach(<STDIN>){
print “I saw $_”;
}
.2 <>
#<>使用@ARGV列表,如果为空则使用标准输入,不为空则顺序执行
while (defined($line = <>)){
chomp($line);
print “It was &line that I saw!\n”;
}
while(<>){
chomp;
print “It was $_ that I saw!\n”;
}
.3 标准输出
print $var1, $var2;
.4 格式化输出
printf "hello %s!", $name;
#其他一些规则
%g #它将根据需要自动选用浮点数,整数,或者指数
%d #整数,去掉小数点后的部分
%2d #
%10s #printf “%10s\n”, “wilma”; #输出为:○○○○○wilma
%-10s #print “%-15s\n”, “flintstone”; #输出为flintstone○○○○
#%f要分小数点前后
printf “%12f\n”, 6*7 + 2/3; #输出为: ○○○42.666667
printf “%12.3f\n”, 6*7 + 2/3; #输出为: ○○○○○○42.667
printf “%12.0f\n”, 6*7 + 2/3; #输出为: ○○○○○○○○○○43
%% #输出为%
print “Monthly interest rate: %.2f%%\n”,5.25/12; #输出的值为0.44%
.5 文件句柄
.1 标准句柄
Perl 自身有六个文件句柄:STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT #可以用管道,重定向改变方向
###$0为程序本身
.2 自定义文件句柄
open CONFIG, “dino”;
open CONFIG, “<dino”;
open BEDROCK, “>fred”;
open LOG,“>>logfile”;
.3 使用文件句柄
#读取
<MYFILE>与<STDIN>一模一样
#写入
print LOG “Captain’s log, stardate 3.14159\n”; #输出到LOG 中
printf STDERR “%D percent complete.\n”, $done/$total * 100;
###文件句柄和要打印的内容之间没有逗号
#改变默认的文件句柄, 不是一个好主意
select LOG;
$| = 1; #don’t keep LOG entries sitting in the buffer 9. 哈希hash
.1 why
机器更擅长处理数字,但对人而言,名字更容易记忆
.2 keys/values
keys 和values 均为任意的标量,key 可以是任意的表达式,但keys 通常转换为字符串,将表达式50/20 作为keys则其通常被转换为3
字符的字符串“2.5”
keys 是唯一的,但values 可以重复。
.3 存取
$hash{$some_key},访问不存在的hash 元素得到undef
$hash{$some_key} = $value;
%some_hash = (“foo”, 35, “bar”, 12.4, 2.5, “hello”, “wilma”, 1.72e30, “betty”, “bye\n”); #列表需要是偶数
%new_hash = %old_hash; #拷贝,很少用,浪费资源
#更明确的赋值
my %last_name = (
“fred” => “flintstone”,
“dino” => undef,
“barney”=> “rubble”;
“betty”=> “rubble”,
);
.4 hash函数
.1 keys, values
keys #返回全部key列表
values #返回全部value列表
#例子
my %hash = (“a”=>1, “b”=>2, “c”=>3);
my @k = keys %hash;
my@v = values %hash;
.2 each
while (($key, $value) = each %hash){
print “$key => $value\n”;
}
#返回key/value顺序是混乱的
.3 foreach
#先排序,后输出
foreach $key (sort keys %hash){
$value =$hass{$key};
print “$key => $value\n”;
#也可以不使用额外的临时变量$value
#print “$key => $hash{key}\n”;
}
.4 exists
#查看相应的key是否存在,value是否为空不重要
if(exists $books{$dino}){
print “Hey, there’s a libaray card for dino!\n”;
}
.5 delete
#删除元素对
delete $books{$person}; #将$person 的借书卡删除掉
.6 整个hash不可内插入字符串
10. 正则表达式
.1 what
匹配模式
.2 最简单的匹配
$_ =“yabba dabba doo”;
if(/abba/){
print “It matched!\n”;
}
.3 元字符
. #任意一个字符,(不包括换行符)
\ #转义
() #分组
| #选择符, or
.4 数量词
* #前面项,重复任意次
.* #叫做“任意字符串匹配模式”(不包括换行符)
+ #前面项,一个或多个
? #前面项,0个或一个
.5 字符类
[] #列表,匹配一个字符,只要列表中有的,[a-zA-Z]范围,[\000-\177]ASKII码,[^def]取反
\d 任何数字的类,[0-9]
\w 被称作“word’字符:[A-Za-z0-9_]。如果你的“words”由通常的字母,数字,下划线组成,那你将非常喜欢它,记住它只匹配一个字符
\s 对于匹配空白,于[\f\t\n\r ] #\s*将匹配任何个数的空白,\s+匹配一个以上的空白
[^\d], [^\w], 和[^\s] #补集, 也可以用\D, \W, \S
[\d\D] #匹配任何一个字符,包括换行符
11. 正则表达式应用
.1 符号
/fred/ #m/fred/的简写,m(fred), m<fred>, m{fred}, m[fred],或者m%fred%, m!fred!, m^fred^都可以
.2 修饰符
#改变默认行为
/yes/i #大小写无关
/ye.s/s #让.可以匹配换行符
/ye s/x #模式中可以添加空白,更易读,匹配时忽略掉.\s(\s*或\s+)来匹配空白
#/x还可以添加注释
/
-? #可选的负号
\d+ #小数点前一个或多个十进制数字
\.? #可选的小数点
\d* #小数点后一些可选的十进制数字
/x #模式结束
#多个修饰符连接使用,不分先后
.3 锚定
#限制搜索位置
^ #开头
$ #结尾 /^fred$/能同时匹配上“fred”和“fred\n”, /^\s*$/,它将匹配一个空行(blank line)
/\bfred\b/可以匹配上单词fred,但不能匹配frederick #词匹配,匹配\w那样的词
\B #\b的补集,注意要分开头与结尾
.4 绑定操作符,=~
#改变正则表达式操作的默认对象$_,而成为=~左边的标量,其优先级较高
my $some_other = “I dream of betty rubble.”;
if($some_other =~ /\brub/){
print “Aye, there’s the rub.\n”;
}
.5 内插
/($reg)/ #将模式部分以变量形式传递,但要注意可能$reg=dsf(sdkf的形式使程序不能工作
.6 匹配变量
$_ = “Hello there, neighbor”;
if(/\s(\w+),/){ #空格和逗号之间的词
print “the word was $1\n”; #the word was there
} #$1,$2,$3对应着相应序号的()匹配的内容
#匹配变量是易失的,第二次匹配时会覆盖第一次的结果;匹配不上时是undef,因此要及时使用或将其转移到普通标量内
.7 古怪而有用的变量
三个变量名为:
$& #整个被匹配的部分
$` #匹配的前一部分`
$' #匹配的后一部分
.8 一般数量词
/a{5,15}/将匹配5 个到15 个a 中的任意一个(包括5,和15)
星号(*)等同于{0,},表示0 个或多个。加号(+)等同于{1,},表示1 个或多个。而问号(?)则等同于{0,1}。
.9 优先级
#要注意优先及,()->数量词->锚定->最低的|
.10 测试程序
#检查你的正则表达式是否正常工作
#! /usr/bin/perl
while(<>){ #一次取一行输入
chomp;
if(/YOUR_PARTTEN_GOES_HERE/){
print “Matched: |$`<$&>$’|\n”; #特殊的变量`
}else{
print “no match: |$_|\n”;
}
}
12. 正则表达式处理文件
.1 替换 s/
# 返回bool值
$_ =“green scaly dinosaur”;
s/(\w+) (\w+)/$2, $1/; #现在为“scaly, green dinosaur”;
s/^/huge, /; #现在为“huge, scaly, green dinosaur”
s/,.*een//; #空替换,现在为“huge dinosaur”
s/green/red/; #匹配失败,仍然为“huge dinosaur”
s/\w+$/($`!)$& /; #现在为“huge (huge !)dinosaur”
s//\s+(!\W+)/$1 /; #现在为“huge (huge!) dinosaur”
s/huge/gigantic/; #现在为“gigantic (huge!) dinosaur”
s/sdfk/aaa/g #/g全部替换
#还可以使用还可以使用/i, /x, 和/s修饰符
.2 分隔符
#不一不定必须使用//
s#^https://#http://#;
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;
.3 绑定
$file_name =~ s#^.*###s; #将$file_name 中所有的Unix 类型的路径去掉, 原字符串会变化
.4 大小写
\U #之后的所有字母大写
\u #下一个字母大写
\L #之后的所有字母小写
\l #之后的一个字母小写
\E #截断影响
\u\L或\L\u #首字母大写,其余小写
.5 split与join
@fields = split /:/, “abc:def:g:h”; #返回(“abc”, “def”, “g”, “h”)
#以空白分割
my $some_input = “This is a \t test.\n”;
my @args = split /\s+/, $some_input; #(“This”, “is”, “a”, “test.”)
#相反的操作
my $x = join“:”, 4, 6, 8, 10, 12; #$x 为“4:6:8:10:12”
.6 用匹配赋值
$_ =“Hello there, neighbor!”;
my($first, $second, $third) =/(\S+) (\S+), (\S+)/;
my $text = “Fred dropped a 5 ton granite block on Mr. Slate”;
my @words = ($text =~ /([a-z]+)/ig);
my $data = “Barney Rubble Fred FlintstoneWilma Flintstone”;
my %last_name = ($data =~ / (\w+)\S+(\w+)/g);
.7 非贪婪的数量词
+?, *?, ??, {x, y}? #只要满足少的匹配即可,先少后多
.8 对多行字符串匹配
#/m
$_ =“I’am much better\nthan Barney is\nat bowling,\nWilma,\n”;
print “Found ‘wilma’at start of line\n”if /^wilma\b/im;
9. 替换多个文件
chomp(my $date = ‘date’);
$^I =“.bak”; #设置备份文件后缀名,.bak文件保持文件的原始状态
while(<>){
s/^Author:.*/Author: Randal L. Scharwartz/;
s/^Phone:.*\n//;
s/^Date:.*/Date: $date/;
print;
} 13. 其他控制
.1 unless
if 控制结构中,只有条件为真时,才执行块中的代码。如果你想在条件为假时执行,可以使用unless,也可以有else
.2 希望将while 循环的条件部分取反。此时,可以使用until
.3 表达式修饰符
print “$n is a negative number.\n”if $n<0; #显得非常紧凑
.4 裸块
#主要目的是提供变量小的作用域
{
body;
}
.5 elsif 语句
#Perl 没有像C 语言“switch”结构中的“fall-through(直接跳入)”下一个代码块的功能
.6 自增和自减
$m++与++$m的区别
.7 for
#同C语言
#for 与 foreach的关系
.8 循环控制
last 会立刻结束循环。(这同C 语言或其它语言中的“break”语句类似)
next 之后,又会进入下一轮循环(这和C 或者类似语言的“continue”相似)
redo。它会调到当前循环块的顶端,不进行条件表达式判断以及接着本次循环
,当Perl 遇见其中之一时,和遇见另一个是一样的。Perl 通过括号能理解你的目的。
.9 标签
LINE: #一般大写,以与函数名区分
last LINE; next LINE; redo LINE; #非常像goto
.10 短路操作
my $last_name = $last_name{$someone} ||‘(No last name)’;
.11 三元操作符?:
像if-then-else 一样
my $size =
($width < 10 ) ? “small”:
($width < 20) ? “medium”:
($width < 50) ? “large”:“extra_large”; #default
#1,100随机数int(1+ rand 100); 14. 文件检验
.1 判断标识符图表
.2 stat and lstat
#stat返回文件的全部属性
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blockes)
= stat($filename);
#lstat是针对链接文件的
.3 localtime
#将时间民戳转成一些有用日期时间变量
.4 位操作
&
|
^
>>
<<
~
.5 位串
"\xAA" | "\x55" #结果是\xFF, 位串可以无限长
.6 _ 文件句柄
#对_文件进行检验时,不进行新的操作,而是从缓存中直接读取上一次的结果
my($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime $timestamp; 15. 目录操作
.1 移动
chdir “/etc”or die “cannot chdir to /etc: $!”; #错误发生时将给变量$!赋值。通常应当检查$!的值
.2 展开文件名匹配
my @all_files = glob “*”;
my @pm_files = glob “*.pm”;
#my@all_files = <*>; ##基本上同@all_files = glob “*”一样;
.3 目录句柄
opendir DH, $dir_to_process or die “Cannot open $dir_to_process: $!”;
foreach $file(readdir DH) {
print “one file in $dir_to_process is $file\n”;
}
closedir DH;
.4 路径
#readdir返回值不包括路径
opendir SOMEDIR, $dirname or die “Cannot open $dirname: $!”;
while (my $name = readdir SOMEDIR) {
next if $name =~ /^\./; #跳过点文件
$name = “$dirname/$name”; #加上目录名
next unless–f $name and –r name; #除非是可读文件
}
.5 递归目录列表
File::Find #这个库可以做到
.6 删除文件
foreach my $file (qw(slate bedrock lava)) {
unlink $file or warn “failed on $file: $!\n”;
}
.7 重命名
rename “over_there/some/place/some_file”, “some_file”;
#批量改名
foreach my $file (glob “*.old”){
my $newfile = $file;
$newfile =~ s/\ .old$/.new/;
if (-e $newfile){
warn“can’t rename $file to $newfile: $newfile exists\n”;
}elsif(rename $file, $newfile){
##成功,什么也不做
} else {
warn “rename $file to $newfile failed: $!\n”;
}
}
.8 链接文件
link“chicken”, “egg” or warn “Can’t link chicken to egg: $!”; #硬连接
symlink “dodgson”, “carroll” or warn “Can’t sysmlink Dodgson to carroll: $!” #软连接
my $where = readlink “carroll”; #得到“dodgson”
my $perl = readlink“/usr/local/bin/perl”#可能得到Perl 放置的地方
unlink linkfile #删除
.9 创建和删除目录
mkdir “fred”, 0755 or warn “Cannot make fred directory: $!”;
#从命令行获取参数
my ($name, $perm) = @ARGV; #前面两个参数是名字和权限
mkdir $name, oct($perm) or die “cannot create $name: $!”; #oct将字符串当成八进制数
#删除目录
File::Path #可以自己写,但最好参数这个库
.10 修改权限
chmod 0755, “fred”, “barney”
.11 改变所有者
my $user = 1004;
my $group = 100;
chown $user, $group, glob “*.o”;
.12 改变时间戳
my $now = time;
my $ago = $now -24*60*60; #一天的秒数
utime $now, $ago, glob “*”; #设成当前访问的,一天之前修改的
16. 字符串和排序
.1 使用索引寻找子串
index("string here!", "her");
.2 substr 操作子串
substr("abc def ghi jkm", 2); #从index 2(这里是c)开始到结尾的子串
substr("abc def ghi jkm", 2, 5); #从index 2(这里是c)开始,截<=5个字符
substr("abc def ghi jkm", -2, 5); #从后向前的index 2(这里是j),截<=5个字符
.3 sprintf
与printf一样,只是不打印出来,而是存储在返回值中
.4 高级排序
sort sub_sort_func @arr; #用户自定义sub_sort_func来对@arr排序
#sub_sort_func的样子
sub sub_sort_func{
$a<=>$b;
}
#$a,$b为系统默认,返回值可能有三个,意思是
sub sub_sort_func {
if($a < $b){-1} elsif($a > $b){1} else {0}
}
#更长见的是$a <=> $b #针对数字; $a cmp $b #针对字符
my @numbers = sort { $a <=> $b } @some_numbers;
my @descending = reverse sort { $a <=> $b } @some_numbers; #反向,或者
my @numbers = sort { $b <=> $a } @some_numbers;
#对Hash排序
my %score = (“barney”=> 50, “fred”=> 205, “dino”=> 30);
my @winners = sort by_score keys %score;
sub by_score {
$score{$b} <=> $score{$a} #按照降序的成绩
or
$a cmp $b; #字母顺序的名字
}
#更夸张的5级排序
@patrons_IDs = sort {
&fines($b) <=> &fines($a) or
$items{$b} <=> $items{$a} or
$family_name{$a} cmp $family_name{$a} or
$personal_name{$a} cmp $family_name{$b} or
$a <=> $b
}
@patron_IDs;
17. 模块的使用
.1 查找
http://search.cpan.org/
.2 判断是否安装过
$perldoc CGI #看有没有CGI的文档
.3 避免冲突
use File:Basename qw/ /; #没有引入函数
my $dirname = File::Basename::dirname $name; #使用模块中的dirname,用全名
use CGI qw(:all); #加载全部函数
.4 DBI模块
use DBI;
$dbh = DBI->connect($data_source, $username, $password);
$sth = $dbh->prepare(“SELECT * FROM fooWHERE bla”);
$sth->execute();
@row_ary = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect();
相关阅读 更多 +
排行榜 更多 +