赞
踩
1. 从一开始, Perl 就设计成可以把简单工作简单化,同时又不失去处理困难问题能力的语言。
因为 Perl 几乎可以在任何地方运行,所以 Perl 可以说是当今最具有移植性的编程环境。
Perl 从一开始就是设计成胶水语言的,可以很方便的调用任意外部程序例如 :my $ret=`echo "xxx"` 。
在每一个层次, Perl 都能够帮助你以最小的忙乱获得最大的享受和进步,这就是为什么这么多 Perl 程序员能够如此悠闲的原因吧
2. 历史上, Perl 要求你在调用的任何用户定义子过程的前面加一个与号( & )(参阅早先时候的 $fido = &fetch(); )。但是到了 Perl 版本 5 ,这个与号是可选的了,所以用户定义动词现在可以和内建动词相同的方法进行调用了( $fido = fetch(); 。
3. 你经常能看见这样来处理单行输入:
chop($number = <STDIN>); # 输入数字并删除新行
还有另外一种写法:
$number = <STDIN>; # 输入数字
chop($number); # 删除新行
4. 请记住在 Perl 里,每个过程都返回值。 C 语言的程序员不会感到奇怪,因为他们已经知道用下面的方法来使变量清零:
$a = $b = $c =0;
真正能使 c 程序员惊讶的是在 Perl 中,赋值语句返回实际的变量作为 lvalue 。因此你可以在同一个语句中多次改变同一个变量的值。例如可以使用下面的语句:
($temp -= 32) *= 5/9
将华氏温度转换成摄氏温度。这也是为什么在本章的前面我们能使用下面的语句:
chop ($number = <STDIN>);
上面的语句能将 $number 最后的值进行 chop 操作。
5.
比较 | 数字 | 字串 | 返回值 |
等于 | == | eq | 如果 $a 等于 $b 返回真 |
不等于 | = | ne | 如果 $a 不等于 $b 返回真 |
小于 | < | lt | 如果 $a 小于 $b 返回真 |
大于 | > | gt | 如果 $a 大于 $b 返回真 |
小于或等于 | <= </td> | le | 如果 $a 不大于 $b 返回真 |
比较 | <=> | cmp | 相等时为 0 ,如果 $a 大为 1 如果 $b 大为 -1 |
6.
7.if 语句
在 C 中,如果你只有一条语句,那么你可以省略花括弧。但是在 Perl 中,花括弧是必须的。
8.
while ($line = <GRADES>) {
这句代码将文件的下一行内容赋值给变量 $line 并且返回 $line 的值,因此 while 语句的条件表达式为真,你也许想知道,当遇到空白行时,Perl 是不是返回假并且过早地退出循环。答案是否定的,如果你还记得我们先前学过的内容,那么理由是非常明显的。读行操作符在字符串最后并不去掉新行符,因此空白行的值是“/n” 。并且我们知道“/n” 不是假值。因此条件表达式为真,并且循环将继续。
9. foreach 的循环变量直接指向元素本身,而不是它的一个拷贝,因此,修改循环变量,就是修改原始数组。
你将发现在 Perl 程序中,foreach 循环比 for 循环要多得多,这是因为 Perl 经常使用一些需要使用 foreach 遍历的各种列表。你经常会看到使用下面的代码来遍历散列的关键字:
foreach $key (sort keys %hash) {
这样就首先将数组按 keys 排列了再循环
10.
跳出控制结构 : next 和 last
11.
一个正则表达式就是一种方法,这种方法能够描述一组字符串,但不用列出所有的字符串
(1) 正则表达式有几种使用方法,第一种,也是最常用的一种,就是确定一个字符串中是否匹配某个模式,因为在一个布尔环境中它们返回真或假。因此当看见 /foo/ 这样的语句出现在一个条件表达式中,我们就知道这是一个普通的模式匹配操作符
(2) 第二种方法,如果你能将一个模式在字符串中定位,你就可以用别的东西来替换它。因此当看见 s/foo/bar/ 这样的语句,我们就知道这表示将 foo 替换成 bar 。
(3) ($good, $bad, $ugly) = split(/,/, "vi,emacs,teco");
(4) 修饰符
12.
特殊符号 /b 匹配单词边界,就是位于单词字符( /w )和非单词字符( /W )之间的零宽度的地方。(字符串的开始和结尾也被认为是非单词字符)。例如 : //bFred/b/ 将会匹配 “The Great Fred” 和 “Fred the Great” 中的 Fred ,但不能匹配 “Frederick the Great” ,因为在 “Frederick” 中的 “d” 后面没有跟着非单词字符。
13 反引用
正则表达式中的一对圆括弧使得这部分匹配到的东西将被记住以供以后使用。
如果你想将一个字符串的前两个词互相调换,你可以使用下面的代码:
/(/S+)/s+(/S+)/$2 $1/
14.
print reverse sort map {lc} keys %hash;
这行代码获取 %hash 的关键字并将它们返回给 map 函数,map 函数使用 lc 将所有的关键字转换成小写,并将处理后的结果传给 sort 函数进行排序,然后再传给 reverse 函数, reverse 函数将列表元素颠倒顺序后,传给print 函数打印出来。
15.
print ++($foo = '99'); # 打印'100'
print ++($foo = 'a0'); # 打印'a1'
print ++($foo = 'Az'); # 打印'Ba'
print ++($foo = 'zz'); # 打印'aaa'
16.
双目 !~ 类似 =~ 操作符,只是返回值是 =~ 的对应返回值的逻辑非。下面的表达式功能上是完全一样的:
$string !~ /pattern/
not $string =~ /pattern/
17.
在列表环境里,如果左操作数是在圆括弧中的列表,x 的作用是一个列表复制器,而不是字串复制器。这个功能对初始化一个长度不定的数组的所有值为同一值时很有用:
@ones = (1) x80; # 一个80 个1 的列表
@ones = (5) x @ones; # 把所有元素设置为5
18.
按位移位操作符(<< 和 >> )返回左参数向左(<< )或向右(>> )移动由右参数声明位(是 bit )数的值。参数应该是整数。比如:
19.
表 3-2 命名单目操作符
-X (file tests) | gethostbyname | localtime | return |
alarm | getnetbyname | lock | rmdir |
caller | getpgrp | log | scalar |
chdir | getprotobyname | lstat | sin |
chroot | glob | my | sleep |
cos | gmtime | oct | sqrt |
defined | goto | ord | srand |
delete | hex | quotemeta | stat |
do | int | rand | uc |
eval | lc | readlink | ucfirst |
exists | lcfirst | ref | umask |
exit | length | require | undef |
20.
范围操作符 .. 根据环境的不同实际上是两种不同的操作符。
在标量环境里,.. 返回一个布尔值。该操作符是双稳定的,类似一个电子开关,并且它仿真 sed ,awk ,和各种编辑器的行范围(逗号)操作符。每个 .. 操作符都维护自身的状态。只要它的左操作数为假就一直为假。一旦左操作数为真,该范围操作符就保持真的状态直到右操作数为真,右操作数为真之后该范围操作符再次为假。该操作符在下次计算之前不会变成假。它可以测试右操作数并且在右操作数变真后在同一次计算中变成假(awk 的范围操作符的特性),不过它还是会返回一次真。如果你不想拖到下一次计算中才测试右操作数(也是 sed 的范围操作符的工作方式),只需要用三个点(... )代替两个点(.. )。对于 .. 和 ... ,当操作符处于假状态后就不再测试右操作数,而当操作符处于真状态后就不再测试左操作数。
返回的值要么是代表假的空字串或者是代表真的一个序列数(从 1 开始)。该序列数每次碰到新范围时重置。在一个范围里的最后序列数后面附加了字串“E0” ,这个字串不影响它的数字值,只是给你一些东西让你可以搜索,这样你可以把终点排除在外。你也可以通过等待 1 的序列数的方法把启始点排除在外。如果标量 .. 的某个操作数是数字文本,那么该操作数隐含地与 $. 变量对比,$. 里包含你的输入文件的当前行号。比如:
if(101 .. 200) {print;}
#
打印第二个一百行
next line if( 1.. /^$/);
#
忽略开头行
s/^/> / if (/^$/ .. eof());
#
引起体
在列表环境里, .. 返回一列从左值到右值计数(以一)的数值。这样对书写 (1 .. 10) 循环和数组片段的操作很有帮助:
for (101 .. 200) {print;} # 打印 101 , 102 。。。 199 , 200
@foo = @foo[0 .. $#foo]; # 一个昂贵的空操作
@foo = @foo[ -5 .. -1]; # 最后5 个元素的片段
因此你可以说:
@alphabet = ('A' .. 'Z');
以获得所有英文字母,或者:
$hexdigit = (0 .. 9, 'a' .. 'f')[$num & 15];
获得一个十六进制位,或者:
@z2 = ('01' .. '31'); print $z2[$mday];
获得带有前导零的日期。你还可以说:
@combos = ('aa' .. 'zz');
获取所有两个小写字符的组合。不过,用下面的语句要小心:
@bigcombos = ('aaaaaa' .. 'zzzzzz');
因为这条语句要消耗很多内存。准确地说,它需要存储 308,915,776 个标量的空间。希望你分配了一个非常大的交换分区。可能你会考虑用循环代替它。
21.
$a = $ok ? $b :$c;
#
得到一个标量
@a = $ok ? @b : @c;
#
得到一个数组
$a = $ok ? @b :@C;
#
得到一个数组元素的计数
22.
$a = $b = $c =0;
把 0 赋予 $c ,其结果(还是 0 )给 $b ,其结果(依然为 0 )再给 $a 。
23.
whie (1) {
...
}
如果你为巡航导弹写代码,你就可能不用什么明确的循环退出了。因为循环会在合适的时间自动退出。
24. 如果你把 “ 文本 ” 的含义尽可能地扩展,那么可能你做的工作中有 90% 是在处理文本
25.
有一个结构元字符是竖直条,表示侯选项:
/Frodo|Pippin|Merry|Sam/ (译注:电影“ 魔戒” 里Shire 的四个小矮人)
这意味着这些字串的任何一个都会触发匹配
26
量词是这些东西:
* + ? *? {3} {2,5}
不过你永远不会看到它们这样独立地存在。量词只有附着在原子后面才有意义
例如: /bar{3}/ , 匹配的是“barrr“
27.
当用于匹配操作时,有时候 =~ 和 !~ 分别读做 “ 匹配 ” 和 “ 不匹配 ”
28. 为了有更好的颗粒度和提高效率,你可以用圆括弧捕捉你特别想分离出来的部分。每对圆括弧捕捉与圆括弧内的模式相匹配的子模式。圆括弧由左圆括弧的位置从左到右依次排序;对应那些子模式的子字串在匹配之后可以通过顺序的变量 $1 ,$2 ,$3 等等获得:
$_ = "Bilbo Baggins's birthday is September 22";
/(.*)'s birthday is (.*)/;
print "Person: $1/n";
print "Date: $2/n";
29. 模式修饰符
/i | 忽略字母的大小写(大小写无关) |
/s | 令 . 匹配换行符并且忽略不建议使用的 $* 变量 |
/m | 令 ^ 和 $ 匹配下一个嵌入的 /n 。 |
/x | 忽略(大多数)空白并且允许模式中的注释 |
/o | 只编译模式一次 |
30. ($lotr = $hobbit ) =~ s/Bilbo/Frodo/g;
如果没有赋值语句周围的圆括弧,你只修改了 $hobbit 并且把替换的个数存储在 $lotr 里,那样会得到很傻的结局
31.
替换一个数组里每个元素:
for (@chapters) { s/Bilbo/Frodo/g }
#
一章一章的替换
s/bilbo/Frodo/g for @chapters;
#
和上面一样的东西
对同一个变量执行重复替换的最经典的方法是用一个单程循环。比如,下面是规范变量里的空白的方法:
for ($string) {
s/^/s+//;
#
丢弃开头的空白
s//s+$//;
#
丢弃结尾的空白
s//s+/ /g;
#
压缩内部的空白
}
32.
tr/aeiou/!/; # 把所有元音字母转换成!
tr{r/n/b/f. }{_};
#
把怪字符转成下划线
tr/A-Z/a-z/ for @ARGV; # 把字符规则化为小写ASCII
$count = ($para =~ tr//n//); # 计算$para 里的换行符
$count = tr/0-9//; # 计算$_ 里的位
$word =~ tr/a-zA-Z//s;
# bookkeeper -> bokeper
tr/@$%*//d;
#
删除这里几个字符
tr#A-Za-z0-9+/##cd; # 删除非base64 字符
#
顺便修改
($HOST = $host) =~ tr/a-z/A-Z/;
$pathname =~ tr/a-zA-Z/_/cs; # 把非ASCII 字母换成下划线
tr [/200-/377]
{/000-/177];
#
剥除第八位,字节操作
33.
表 5-5 。 正则量词
* | 否 | 匹配 0 或者更多次数(最大)。 |
+ | 否 | 匹配 1 或者更多次数(最大)。 |
? | 否 | 匹配 1 或者0 次(最大)。 |
{COUNT} | 否 | 匹配COUNT 次 |
{MIN,} | 否 | 匹配至少MIN 次(最大)。 |
{MIN,MAX} | 否 | 匹配至少MIN 次但不超过MAX 次(最大) |
*? | 否 | 匹配0 或者更多次(最小) |
+? | 否 | 匹配1 或者更多次(最小) |
?? | 否 | 匹配0 或者1 次(最小) |
{MIN,}? | 否 | 匹配最多MIN 次(最小) |
{MIN,MAX}? | 否 | 匹配至少MIN 次但不超过MAX 次(最小) |
表 5-6 扩展的正则序列
(?#...) | 否 | 注释,抛弃 | |
(?:...) | 是 | 只集群,不捕获的圆括弧 | |
(?imsx-imsx) | 否 | 打开/ 关闭模式修饰词 | |
(?imsx-imsx:...) | 是 | 集群圆括弧加修饰词 | |
(?=...) | 否 | 如果前向查找断言成功,返回真 | |
(?!...) | 否 | 如果前向查找断言失败,返回真 | |
(?<=...) </td> | 否 | 如果前向查找断言成功,返回真 | |
(? | 否 | 如果前向查找断言失败,返回真 | |
(?>...) | 是 | 匹配未反向跟踪的子模式 | |
(?{...}) | 否 | 执行嵌入的Perl 代码 | |
(??{...}) | 是 | 匹配来自嵌入Perl 代码。 | |
(?(...)... | ...) | 是 | 匹配if-then-elase 模式 |
(?(...)...) | 是 | 匹配if-then 模式 |
|
表 5-7 。字母数字正则元符号
/0 | 是 | 匹配空字符(ASCII NUL )。 |
/NNN | 是 | 匹配给出八进制的字符,最大值为/377 。 |
/n | 是 | 匹配前面第n 个捕获字串(十进制)。 |
/a | 是 | 匹配警钟字符(BEL )。 |
/A | 否 | 如果在字串的开头为真 |
/b | 是 | 匹配退各字符(BS )。 |
/b | 否 | 在字边界为真 |
/B | 否 | 不在字边界时为真 |
/cX | 是 | 匹配控制字符 Control-x (/cZ ,/c[ ,等)。 |
/C | 是 | 匹配一个字节(C 字符),甚至在utf8 中也如此(危险) |
/d | 是 | 匹配任何数字字符 |
/D | 是 | 匹配任何非数字字符 |
/e | 是 | 匹配逃逸字符(ASCII ESC ,不是反斜杠)。 |
/E | —— | 结束大小写(/L ,/U )或者掩码(/Q )转换 |
/f | 是 | 匹配进页字符(FF )。 |
/G | 否 | 如果在前一个m//g 的匹配结尾位置时为真 |
/l | —— | 只把下一个字符变成小写 |
/L | —— | 把/E 以前的字母都变成小写 |
/n | 是 | 匹配换行符字符(通常是NL ,但是在Mac 上是CR )。 |
/N{NAME} | 是 | 匹配命名字符(/N{greek:Sigma} )。 |
/p{PROP} | 是 | 匹配任何有命名属性的字符 |
/P{PROP} | 是 | 匹配任何没有命名属性的字符 |
/Q | —— | 引起(消元)直到/E 前面的字符 |
/r | 是 | 匹配返回字符(通常是CR ,但是在Mac 上是NL )。 |
/s | 是 | 匹配任何空白字符。 |
/S | 是 | 匹配任何非空白字符。 |
/t | 是 | 匹配水平制表符(HT )。 |
/u | —— | 只把下一个字符变成标题首字符 |
/U | —— | 大写(不是标题首字符)/E 以前的字符。 |
/w | 是 | 匹配任何“ 字” 字符(字母数字加"_" )。 |
/W | 是 | 匹配任何“ 非字” 字符。 |
/x{abcd} | 是 | 匹配在十六进制中给出的字符。 |
/X | 是 | 匹配Unicode 里的” 组合字符序列“ 字串。 |
/z | 否 | 只有在字串结尾时为真 |
/Z | 否 | 在字串结尾或者在可选的换行符之前为真。 |
如果在 /p 和 /P 里的属性名字是一个字符,那么花括弧是可选的。如果 /x 里的十六
33.
锁有两种变体,共享( LOCK_SH 标志)和排它( LOCK_EX 标志)。尽管听着有 “ 排它 ” 的意思,但是进程并不需要服从对文件的锁。也就是说, flock 只是实现了劝告性的锁定,劝告性的锁定,也就意味着锁定一个文件并不阻止其他的进程读取甚至是写入该文件。进程请求一个排它锁只是让操作系统推迟它对文件的处理,直到所有当前的锁持有者,不管是共享锁还是排它锁,都完成操作以后才进行。类似地,如果一个进程请求一个共享锁,它只是推迟处理直到没有排它锁存在。只有所有当事人都使用文件锁机制的时候,你才能安全地访问一个有内容的文件
34. 下面这个最简单的例子打开一个文件然后开始一个子进程。然后子进程则使用已经为它打开了的文件句柄
open (INPUT, "< /etc/motd") or die "/etc/motd: $!";
if ($pid = fork ) { waitpid ($pid, 0);}
else {
defined ($pid) or die "fork : $!";
while (<INPUT>) { print "$.: $_" }
exit ; # 不让子进程回到主代码
}
# INPUT 句柄现在在父进程里位于 EOF
35
use Thread qw /async yield/;
my $var = 0;
sub abump {
if
($var == 0) {
yield;
$var++;
}
}
my $t1 = new Thread /&abump;
my $t2 = new Thread /&abump;
for my $t ($t1, $t2) { $t->join }
print "var is $var/n";
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。