最近事情有点多,没有什么时间来记录学习历程。月初的时候在网上买了本英文版的《Effective Perl》,被誉为"圣经"的perl系列教程必须拜读一下。接下来的每一周我会整理出两个章节的内容。
第一章节主要介绍perl基础部分需要注意的细节。
- Understand what sigils are telling you
sigils(魔符)指的是perl变量名前和去引用前的标识
$ 意味着你正在操作的是一个单一的值,这个值可能是一个标量变量也或者是哈希或者数组的单一元素
$scalar
$array[3]
$hash{'key'}
@ 意味着你正在操作的是多个值的集合,你能在数组和哈希中使用它
@array
@array[1,2,3]
@hash{qw(key1 key2)}
% 意味着你把一些东西当作哈希处理
% hash
不能通过魔符来识别变量的类型,我们能通过三个考量因素来进行判断: 魔符、标识符、索引
魔符 标识符 索引
$ name [3]
$ hash {'key'}
通过索引[ ]或{ },我们可以确定变量为数组和哈希
如果没有索引符号,通过魔符标识即可确定变量类型
- know the difference between string and numeric comparisons
用来比较字符串的操作符也是由字母组成,字符比较是一个字符一个字符按照字符的值进行比较,并且区分大小写和空格
'a' lt 'b' #TRUE
'a' eq 'A' #false
'john' eq 'john ' #false
数值比较操作符使用和代数里面的符号差不多
0 < 5 #TRUE
10 == 10.0 #TRUE
不要使用数值比较操作符比较字符串,反之亦然。
为了避免弄混eq和==,我们可以使用只能匹配操作符~~来搞定各种比较操作,它会检查两边的类型找出合适的方法来比较
当智能匹配操作符发现右边是数字,或者左边是数字而右边像数字的字符串时候,它会按 == 的方式作比较
if (123 ~~ '456') {...} # FALSE
if ('123.0' ~~ 123){...} #TRUE
if ('mimi' ~~ 123) #FALSE
否则智能匹配操作符会按 eq 的方式来比较
if ('123' ~~ '123.0') #FALSE 等价于eq
- know which values are false and test them accordingly
因为数值和字符串类型的数据在perl中都属于标量,而布尔操作符能针对任何标量进行操作,所以perl 的逻辑真假测试,可以根据数字和字符串的取值判别。
0 ,'0',undef, ' '(空字符串)都是假值,其他皆为真
在哈希中,我们用defined来判断某个key的value是否被定义,而exists则是判断是否存在该键名
$hash{'key'} = undef;
if ($hash{'key'}) #FALSE
if (exists $hash{'key'}) #TRUE
if (defined $hash{'key'}) #FALSE
如果某个键的赋值明确,哪怕是个代表假的值,这个键对应的值也是已定义的
$hash{'key'} = ' ';
if ($hash{'key'}) #FALSE
if (exists $hash{'key'}) #TRUE
if (defined $hash{'key'}) #TRUE
# 当用while读入文件时,行输入操作符<>对于$_变量会自动check $_是否被定义,如果没有定义,则会退出while 循环,结束读入文件. 若不使用$_变量,则需要check变量是否被定义
while (defined(my $line) = <IN>) {...}
- know the differene between lists and arrays
列表是一组标量的有序结合,然而数组是一个含有列表的变量,数组并非列表本身,而是列表的容器
(localtime)[5] #列表
$array[5] #数组
对于数组,在标量上下文则返回数组中元素的个数,然而对于列表没有这样的操作,列表没有标量解释。
逗号操作符分隔的一串标量
my $scalar = ('a','b','c');
print $scalar; # 有人猜结果为3,其实不是,为c. 逗号操作符在标量上下文中会返回右边的元素
标量上下文中的列表赋值操作,会返回赋值操作符右边的元素个数
my $scalar = my @array = localtime
此时会返回localtime产生的元素个数,赋值操作符是右结合的,先进行最右边的列表赋值,即: 标量上下文环境中列表赋值操作,会返回赋值操作符右边的元素个数
为了方便可以省略中间数组的命名,可以替换上面的@array为一个空列表
my $scalar = () = localtime # 称为山羊操作符
my $number = () = split /:/,$line
my $number = () = m/(...)/g; #统计全局匹配的个数
- Avoid a slice when you want an element
@a[1]实际上是一个数组切片,获取数组中的某个元素应该使用$array[$n]
切片是一种同时访问多个元素的快捷方式
my @select = ($array[1],$array[2]) # 重复输入array,很啰嗦
my @select = @array[1,2] #使用切片更加简洁
# 左值切片
在赋值操作中,如果左边是一个切片,那就相当于对切片中的变量元素依次赋值
@array[1,2] = ('a','b');
# 切片可以交换数组内的元素
@array[1,2] = @array[2,1] #swap 1st and 2nd
# 合并两个哈希
@hash{keys %hash1} = value %hash1;
%hash = (%hash,%hash1) # 于上面结果相同,但很晦涩难懂
# 将一个哈希从另一个哈希中去除
delete @name{keys %remove}
通常我们会这么做
foreach my $k (keys %remove) {
delete $name{$k};
}
切片很方便,但是切记对于单个元素不要用切片
- Understand context and how it affects operations
当操作的需要的是单个对象时,perl会使用标量上下文,当操作多个对象时,perl 使用的就是列表上下文。
列表操作符希望操作的是多个元素,如print 操作符
6.1 由赋值操作决定的上下文
如果是赋值给某个列表,那么赋值操作符会给它右边提供列表上下文环境
my ($n) = ('a','b','c') #$n ='a'
my @lines = <IN> #读入所有行
给裸标量赋值(赋值操作符左边没有用括号)指定的就是标量上下文
my $n = ('a','b','c'); # $n = 'c'
以上是我觉得比较重要的东西,这本书内有很多的有意思的东西,值的我去仔细研读。
关于平常练习使用的perl脚本,我会及时上传到Github上:
https://github.com/chensole/perl_practice
网友评论