perl习语(idioms)
01 Dec 2015There’s more than one way to do it.
The notes are based on “Idiomatic Perl” - Dave Cross.
在使用perl完成了一个测试框架和看了不少资料后,留下了一些笔记。
-
||和or的优先级不同||优先级高,or优先级低,这造成了很多问题。$a = $b or $c; #这样用or有问题 ($a = $b) or $c; #实际得到 $a = $b || $c; #应该用|| open FILE, $file || die("open $file fail"); #这样用||有问题 open FILE, ($file || die("open $file fail")); #实际得到 open FILE, $file or die("open $file fail"); #应该用or -
设定默认值
my $time = shift || "0:0:0";潜在问题是shift出来的是0或者’‘,而且0或者’‘是希望得到的值。 因为这时$time会得到”0:0:0”。
perl5.10引入了//解决这个问题。
my $time = shift // "0:0:0";这时$time会得到希望的0或者’‘。
-
写文件
sub write_file { my ($filename, $content) = @_; open (my $wfh, '>', "$filename") || croak("cannot write file $filename"); for (@{$content}) { print $wfh $_; } # close tsc file close $wfh; } -
use Carp;
使用Carp的好处确实很多。它可以得到message从哪里抛出来的。 carp, cluck, croak, confess的区别主要如下:
Fatal Backtrace carp N N cluck N Y croak Y N confess Y Y -
用来计算成功,失败运行的个数
my %test_status = ( total_dif => \@dif_tests, total_suc => \@suc_tests, ... ) my $totalsuc = scalar @{$test_status->{total_suc}}; ... -
用来自定义排序
sub sort_custom { my ($array, $wfh, $compare_method) = @_; if ($array) { foreach (sort $compare_method @$array) { ... } } } sort_custom($test_status->{total_tests}, $result_filename, \&compare_by_testname); sub compare_by_testname { my @ta = split('\t',$a); my @tb = split('\t',$b); my $testnamea = $ta[0]; my $testnameb = $tb[0]; $testnamea cmp $testnameb; } -
用map和grep来取不重复的元素
sub uniq_test { my $arr = shift; my %temp_hash; my @result = grep { ! $temp_hash{(split('\t', $_))[0]}++ } map lc, @{$arr}; return \@result; } -
创建dispatch,根据不同参数调用不同的程序
my %arg_dispatch_table = ( component => \&p_component, testname => \&p_testname, ... ) -
将hash改造成set用
%humped = { camel => 1, dromedary => 1, }; $humped{$animal} or die "$animal has no humps\n"; -
my vs local
my和local的区别,在网上这个程序演示很棒。
如果$var是local,得到的结果是4 10 11 4
如果$var是my,得到的结果是4 10 10 5
$var = 4; print $var, "\n"; hello(); print $var, "\n"; # subroutines sub hello { local $var = 10; # change here for testing print $var, "\n"; gogo(); # calling subroutine gogo print $var, "\n"; } sub gogo { $var ++; } -
perl会把array flatten
@arr_2d = ((1, 2, 3),(4, 5, 6),(7, 8, 9));@arr_2d 得到的是 (1, 2, 3, 4, 5, 6, 7, 8, 9)
-
如果要创建2维的array
@arr_2d = ([1, 2, 3],[4, 5, 6],[7, 8, 9]);$arr_2d[1] 是 (4, 5, 6)
$arr_2d[1]->[1] 是 5
-
The Schwartzian Transform 这个施瓦茨变换太棒了。
@data_out = map { $_->[1] } sort { $a->[0] cmp $a->[0] } map { [func($_), $_] } @data_in; -
很多程序里面会省略这个默认变量$_
-
默认的记录分隔变量$/
-
一口吃下整个文件
$/ = undef; -
相当于使用’paragraph’模式.
$/ = ''; # empty string -
打印当前记录号$.
while (<FILE>) { print "$.: $_"; } -
$,是输出field分隔符, 默认值是empty string
@nums = 1 .. 3; print @nums; # 123 $, = ' - '; print @nums; # 1 - 2 - 3 -
$”是list分隔符, 默认值是space
@nums = 1 .. 3; print "@nums"; # 1 2 3 $" = '|'; print "@nums"; # 1|2|3 -
$!存储了最后一个os调用的错误
open FILE, 'file' or die $!; -
$?存储了最后一个子进程的错误
@file = `ls`; die $? if $?; -
$@存储了最后一个”eval”调用的错误
eval { require Module }; die $@ if $@; -
$0当前程序名
-
$$当前进程号
-
$^O存储当前操作系统
-
%ENV存储所有环境变量
-
matched patterns,$1, $2…
$_ = 'This is a string'; if (/is (\w+) (\w+)/) { print "$1 : $2\n"; } -
grep
grep作用在每个元素,每个元素记录在$_,如果符合{}中的判断,才加入到输出列表
@odds = grep { $_ % 2 } @ints; -
map
map作用在每个元素,每个元素记录在$_,所有元素经过{}中的处理,都加入到输出列表
@squares = map { $_ * $_} @ints; -
用qq和q方便的表示双引号和单引号
print "<img src=\"$file\" width=\"100\" height=\"50\">"; print qq(<img src="$file" width="100" height="50">); q!some text! @days = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); @days = qw(Sun Mon Tue Wed Thu Fri Sat);