切片:
my (undef, $card_num, undef, undef, undef, $count) = split /:/;
定义undef的话,会默认忽略匹配的变量
更好的方法:
列表切片
my $mtime = (stat $some_file)[9]; #取得文件的第10个属性
my $card_num = (split /:/)[1];
my $count = (split /:/)[5];
一次获得两个值:
my ($card_num, $count) = (split /:/)[1, 5]; #取出1,5
从列表中取出第一个和最后一个元素,借助索引-1代表最后一个元素这一事实:
my ($first, $last) = (sort @names)[0, -1];
my @numbers = (@names)[9, 0, 2, 1, 0];
数组切片:
切片总是一个列表,所以数组切片总是使用一个@符号来标示,当你看见类似@names[...]之类的写法时,需要以perl的习惯来看开头的符号和结尾的方括号,方括号意味着你要检索数组成员,@符号则意味着获取的是整个列表,而$符号意味着获取单个元素。
但有一个切片可以工作,列表却不能的场合,那就是切片可以被直接内插到字符串中去:
my @names = qw{zero one three four five six seven eight nine};
print "Bedrock @names[9, 0, 2, 1, 0]";
如果我们想要内插@names,就会得到数组所有成员构成的字符串,元素之间用空格隔开,如果我们要内插的是@names[9, 0, 2, 1, 0], 就会得到指定数组元素构成的字符串,同样用空格隔开,让我们回到Bedrock图书馆的例子,假设我们的程序需要修改读者Slate先生的地址和电话号码,因为他刚刚搬到了Hollyrock山庄的某间大房子,如果我们得到一个存有关于他的信息列表的@items,那么就可以按如下方式简单的修改数组中的那两个元素:
my $new_home_phone = "555-6099";
my $new_address = "99380 Red Rock West";
@items[2, 3] = ($new_address, $new_home_phone);
哈希切片:
和数组切片相似,也可以用哈希切片(hash slice)的方式从哈希里切出一些元素,还记得三个选手的保龄球积分吗?她们存放在哈希%score中,我们可以用哈希元素所构成的列表来取出这些积分,或是使用切片,这两个技巧实际效果相当,但第二种做法更加简洁高效:
my @three_scores = ($score("barney"), $score{"fred"}, $score{""dino});
my @three_scores = @score{qw/barney fred dino/};
切片一定是列表,因此哈希切片也是用@符号来标示。
my @player = qw(barney fred dion);
my @bowling_scores = (195, 205, 30);
@sorce{@player} = @bolwing_socres;
哈希切片也可以被内插进字符串:
print "Tonight's Player were: @players\n";
print "Their scores were: @score{@players}";
捕获错误:
用eval:
检查运行时错误,用eval包起来
eval{$barney = $fred / $dino};
现在即使是$dino为0也不会造成程序崩溃
eval的返回值就是运距块中最后一条表达式的执行结果,常这样写:
my $barney = eval {$fred / $dino};
print "I couldn't divie by \$dino:$@" if $@;
unless(eval{$fred / $dino})
{ print "I couldn't divide by \$dino: @$" if @!; }
总共有4种类型的错误是eval无法捕获的:
第一种:是出现在源代码中的语法错误,比如没有匹配的引号,忘写分号,漏写操作符,或者非法的正则表达式等。
第二种:是让perl解释器本身崩溃的错误,比如内存溢出或者受到无法接管的信号。
第三种:是eval无法捕获的错误是警告,不管是由用户发出的(通过warn函数),还是perl自己内部发出的(通过打开-W这个命令行选项,或者使用use warning编译指令。要让eval捕获警告专门的一套机制,请参考perl文档中_WARN_伪信号相关的内容)
第四种:是exit操作符会立即终止程序运行,就算从eval块内部的子程序来调用它
为了安全不要在程序里用eval,只有在相当关注安全时才应该使用eval。
任何出现在字符串中的东西都会被当做perl代码来解释执行:
my $operator = 'unlink';
eval "operator \@files";
更高级的错误处理:
eval{ die "adfsasdfas"
die "adfasd";;};
Try::Tiny模块从CPAN下载:
use Try::Tiny;
try
{
}
catch
{
}
finally
{
这永远被执行到,以便实施清理工作
}
autodie:
use autodie;
open my $fh, '>', $filename; #仍旧会在错误发生时调用die函数
use autodie qw(open system:socket);
grep筛选列表:
得到奇数:
my @odd_numbers = grep($_ % 2) 1..1000;
从文件中取出包含fred的行:
得到符合的行结果:
my @matching_lines = grep{/\bfred\b/i}<$fh>;
my @matching_lines = grep /\bfred\b/i, <$fh>;
得到符合的行的数量:
my $line_count = grep /\bfred\b/i, <$fh>;
这就是上下文不同得到结果不同的很好解释
用map把列表元素变形:
my @data = (4.75, 1.5, 2, 1234, 6.456, 12345, 23.94);
my @formatted_data = map {&big_money($_)} @data;
my @formatted_lines
map的结果可以当成其他函数的参数传递
print "The money numbers are:\n";
map {sprintf("%25s\n", $_)}@formatted_data;
当然不用临时数组也是可以的;
my @data = (4.75, 1.5, 2, 1234, 6.456, 12345, 23.94);
print "The money numbers are:\n", map{sprintf("%25s\n", &big_money($_))}@data;
简单点:
print "Some powers of two are:\n",
map "\t" . (2 ** $_) . "\n", 0..15;
更花哨的列表工具:
List::Util模块包含在标准库中,它提供各式高效的常见列表处理工具,都是用c语言实现的。
简洁的:
use List::Util qw(first);
my $first_match = first{/\bPebbles\b/i}@characters;
use List::Util qw(sum);
my $total = sum(1..100); #得到总和500500
use List::Util qw(max);
my $max = max(3, 5, 10, 4, 6);
字符串的话:
use List::Util qw(maxstr);
my $max = maxstr(@strings);
如果对列表中的元素随机排序的话,可以用shuffle实现:
use List::Util qw(shuffle);
my @shuffle = shuffle(1..1000); #使列表元素的排序随机
不是CPAN自带的第三方模块:List::MoreUtils;
use List::MoreUtils qw(none any all);
if(none {$_ > 100}@numbers)
{ print "No elements over 100\n"; }
elsif(any {$_ > 50}@numbers )
{ print "Some elements over 50\n"; }
elsif(all {$_ < 10}@numbers )
{ print "All elements are less than 10\n"; }
如果需要对按元素组处理列表的话,可以用natatime来取出对应位置上的元素:
use List::MoreUtils qw(natatime);
my $iterator = natatime 3, @array;
while (my @triad = $iterator->())
{ print "Got @triad\n"; }
如果要合并两个或多个列表,可以用mesh构造一个大型列表,交错填充原始列表中各个位置上的元素,就算其中某个列表长度很小都没关系:
use List::MoreUtils qw(mesh);
my @abc = 'a' .. 'z';
my @numbers = 1 .. 20;
my @dinosaurs = qw(dino);
my @large_array = mesh @abc, @numbers, @dinosaurs;
Perl语言入门笔记 第十七章 高级perl技巧(eval, grep, map)
于 2015-09-21 02:11:21 首次发布