加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl语言入门笔记 第十七章 高级perl技巧(eval, grep, map)

发布时间:2020-12-15 23:40:27 所属栏目:大数据 来源:网络整理
导读:=pod第十七章高级perl技巧切片:my (undef,$card_num,undef,$count) = split /:/;定义undef的话,会默认忽略匹配的变量更好的方法:列表切片my $mtime = (stat $some_file)[9]; #取得文件的第10个属性my $card_num = (split /:/)[1];my $count = (split /:/)
=pod
第十七章	高级perl技巧

切片:
	my (undef,$card_num,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,2,1,0];

数组切片:
	切片总是一个列表,所以数组切片总是使用一个@符号来标示,当你看见类似@names[...]之类的写法时,需要以perl的习惯来看开头的符号和结尾的方括号,方括号意味着你要检索数组成员,@符号则意味着获取的是整个列表,而$符号意味着获取单个元素。

	但有一个切片可以工作,列表却不能的场合,那就是切片可以被直接内插到字符串中去:
		my @names = qw{zero one three four five six seven eight nine};
		print "Bedrock @names[9,0]";
	如果我们想要内插@names,就会得到数组所有成员构成的字符串,元素之间用空格隔开,如果我们要内插的是@names[9,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: @playersn";
			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{/bfredb/i}<$fh>;
			my @matching_lines = grep /bfredb/i,<$fh>;
		得到符合的行的数量:
			my $line_count = grep /bfredb/i,<$fh>;
			
这就是上下文不同得到结果不同的很好解释

用map把列表元素变形:
	my @data = (4.75,1.5,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("%25sn",$_)}@formatted_data;
		
	当然不用临时数组也是可以的;
		my @data = (4.75,23.94);
		print "The money numbers are:n",map{sprintf("%25sn",&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{/bPebblesb/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 100n"; }
			elsif(any {$_ > 50}@numbers )
			{ print "Some elements over 50n"; }
			elsif(all {$_ < 10}@numbers )
			{ print "All elements are less than 10n"; }
			
			如果需要对按元素组处理列表的话,可以用natatime来取出对应位置上的元素:
				use List::MoreUtils qw(natatime);
				my $iterator = natatime 3,@array;
				while (my @triad = $iterator->())
				{	print "Got @triadn"; }
				
	如果要合并两个或多个列表,可以用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;	
	
=cut

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读