Perl语言入门14-17
---------第十四章 字符串与排序-------------------
index查找子字符串
my $stuff = "howdy world!";
my $where = index($stuff, "wor"); #6
#返回首个字符匹配的位置,字符串第一个位置为0,上例即wor匹配的w位置
#无法匹配返回-1
my $here = index($stuff,"w",2); #返回2(从2+1个字符开始)
my $there = index($stuff,"w",3); #返回6
rindex从末尾开始找起,基本用不到
substr操作子字符串
#第二个参数:起始位置,第三个参数:截取长度
my $minx = substr("fred J. Flintstone", 8, 5); #Flint
my $peb = substr "fred J. Flintstone", 13; #stone 不加第三个参数,默认到最后
my $out = substr("some very long string",-3,2); #in 倒数第三个字符开始
#与index结合使用
my $long = "some very very long string";
my $right = substr($long, index($long,"l"); #long string
#修改字符串
my $string = "hello, world";
substr($string, 0, 5) = "goodbye"; #goodbye, world 可见长度不一定相同
#替换
substr($string, -20) =~ s/fred/barney/g; #只替换字符串后20个中匹配字符
sprintf格式化字符串
不同于printf的是它能赋值给变量
my $date = sprintf "%4d %02d",$yr,$mo;
my $money = sprintf "%.2f",2.3456;
排序
#数组排序
my @numbers = sort {$a <=> $b} @some_numbers; #数值
my @string = sort {$a cmp $b} @some_strings; #字符串
my @descending = reverse sort {$a <=> $b} @some_numbers;
my @descending = sort {$b <=> $a} @some_numbers; #结果同上
#哈希值排序
sort keys %hash #这是对键排序
sort{$hash{$b} <=> $hash{$a}} keys %hash #值排序,降序
sort{$hash{$a} <=> $hash{$b}} keys %hash #升序
#sort values %hash ???
#先按值再按键排序
my @winner = sort by_score_name keys %score;
sub by_score_name{
$score{$b} <=> $score{$a} #根据分数降序排列
or
$a cmp $b #分数相同再按名字排序
}
#飞船操作符返回-1或1,都为真,两数相同时返回0。
#再加or,可进行多级排序
-------第十五章 智能匹配与given-when结构------------
智能匹配操作符~~
会根据两边操作数的数据类型自动判断何种方式进行比较和匹配,一般与前后顺序无关,特殊情况外。
say "I found fred in the same" if $name ~~ /Fred/;
对不同操作数的处理:
%a ~~ %b #键是否相等
%a ~~ @b 或@a ~~ %b #a键是否在数组b中
%a ~~ /fred/ 或/fred/ ~~ %b #键匹配
'fred' ~~ %a #哈希值$a{fred}是否存在
@a ~~ @b #数组是否相同
@a ~~ /fred/ #数组中至少一个元素匹配
$name ~~ /fred/ #模式匹配
'fred' ~~ 'fred' #字符串是否相同
123 ~~ 456 #数组是否相等
示例1:%names中是否匹配fred键,若有打印
#传统写法:
my $flag = 0;
foreach my $key (keys %name){
next unless $key =~ /fred/;
$flag = $key;
last;
}
print "the key is $flag\n" if $flag;
#智能匹配:
say "sucess" if %names ~~ /fred/; #或if /fred/ ~~ %names
示例2:判断两个等长的数组是否完全相同
#传统写法:
my $equal = 0;
foreach my $index (0..$#names1){
last unless $names1[$index] eq $names[$index];
$equal++;
}
print "yes\n" if $equal == @names1;
#智能匹配:
say "yes" if @names1 ~~ @names2;
- given语句
given-when多条件,类似c语言switch语句。
given ($ARGV[0]){
when('fred'){say "1"} #实际是$_ =~ 或$_ ~~
when(/Fred/i){say "2"}
when(/\AFred/){say "3"}
default {say "4"}
}
#和if-elsif-else语句的区别在于:given-when可在满足某条件的基础继续测试其他条件,而if-else-elsif-else则非此即彼。
#每个条件也可加break/continue等控制
多个条目的when匹配
将given放到foreach中循环测试
foreach my $name(@names){
given($name){
...
}
}
##可简化以下形式:
foreach(@names){ #不使用具名控制变量
say "\nProcessing $_";
when('fred'){say "1"; continue} #continue使每个条件都能执行
when(/Fred/i){say "2"; continue}
when(/\AFred/){say "3"}
say "moving on to default...";
default {say "4"}
}
----------第十六章 进程管理----------------------
system函数
perl程序为父进程,system为子进程。
#一般就是shell命令。
system 'date';
system 'ls -l $HOME';
#此处用双引号,会将$HOME视为变量内插,而非环境变量
system 'for i in *; do echo ==$i==; cat $i; done &';
#里面的命令为孙进程;&放后台运行,perl程序无需等待它运行完
#不使用shell命令,则用多参数:
system 'tar','cvf',$tarfile, @dirs;
环境变量
%ENV : 每个键都代表一个环境变量
$ENV{'PATH'} = "/home/rootbeer/bin:$ENV{'PATH'}";
其他类system函数和命令
#1.exec函数
exec 'date';
#不能在后台运行,一般很少用
#2. 反引号
print "the time is now: ", `date`;
my $out_errors = `frobnitz -enable 2>&1`; #将标准错误合并至标准输出
#建议如果不需要捕获输出内容,就不要用反引号。
#3. qx操作符
qx(perldoc -t -f int) #近似反引号
#建议还是用system函数
------第十七章 高级Perl技巧-------------------
切片
#标量:
my $count = (split /:/)[5];
my($card,$count) = (split /:/)[1,5];
my($first, $last) = (sort @names) [0,-1] #取第一个和最后一个
#数组切片:
my @num = @names[9,2,1,0,1];
#下标可任意顺序,也可重复
#哈希切片:
my @three_scores = @score { qw/barney fred dino/ }
#等于:my @three_scores = ($score{"barney"}, $score{"fred"}, $score{"dino"});
my @name = qw /a b c/;
my @math_score = qw /1 2 3/;
@score{@name} = @math_score; #相当于构建哈希
print "their scores were: @score{@name}\n"; #也能内插
捕获错误
- eval表达式
检查到致命错误立即停止运行整个eval块,退出后继续运行其余代码。
默认返回语句块最后一条表达式结果。若捕获到错误,整个语句块返回undef,并在特殊变量$@中设置错误消息。
#如对除0错误的处理:
my $barney = eval {$fred/$dino} // 'NaN'; #将NaN设为默认值
print "I can't divide by \$dino : $@" if $@;
#检查返回值来判断
unless (eval { $fred/$dino}){
print "I can't divide by \$dino : $@" if $@;
}
#对多处潜在(打开文件/除0/子程序等)的致命错误做防范:
foreach my $person (qw /one wtow three four/){
eval{
open my $fh, '<', $person or die "can't open file: $!";
my ($total, $count);
while(<$fh>){
$total += $_;
$count++;
}
my $average = $total/$count; #eval也可在此嵌套
print "average for file $person was $average\n";
&do_something($person,$average);
}
if($@){
print "an error occurred ($@),continuing\n";
}
}
#但有些错误是eval无法捕获的:
#如语法错误;perl解释器崩溃;警告信息;exit操作符
高级错误处理
Perl语言处理错误的基本做法:用die抛出异常,用eval捕获异常,通过识别$@中的错误消息判断问题出在哪里。
#local $@;
eval{
...;
die "a unexpected message" if $unexpected;
die "bad denominator" if $dino == 0;
$barney = $fred/$dino;
}
if( $@ =~ /unexpected/){...;}elsif($@ =~ /denominator/){...;}
#这类代码有很多弊端,如$@的动态作用域问题,确保不干扰高层eval错误。
#这里最好在最前加上local $@;
#Try::Tiny模块解决这类问题:
use Try::Tiny;
try{...;} #可能抛出异常的代码
catch{...;} #处理异常的代码
finally{...;} #不管是否出错都运行的代码
my $barney =
try{$fred/$dino}
catch{say "error is $_";} #$_替代$@,避免干扰
finally{say @_? 'error' : 'worked';}; #@_判断参数内容
#autodie:
#perl自带autodie编译指令,自动抛出异常
use autodie;
open my $fh, '>', $filename;
grep函数处理列表元素
返回真假值
my @odd_numbers = grep { $_ % 2} 1..1000; #挑出奇数
my @match_lines = grep {/\bfred\b/i} <$fh>;
my @match_lines = grep /\bfred\b/i/, <$fh>;
#若只有一个表达式,可去掉大括号加逗号进行简化
my $line_count = grep /\bfred\b/i, <$fh>; #标量,返回匹配个数
map函数处理列表元素
返回实际结果
my @data = (4.5,6.23,67);
my @format_data = map {&big_money} @data; #对金额数字格式化
print "the money are: \n", map {sprintf("%25s\n", $_)} @format_data;
#简单表达式同样可简化:
print "some powers of two are:\n",
map "\t".(2**$_)."\n", 0..15;
其他处理列表元素函数
Perl自带的List::Util模块
#first函数:
my $first_match = first {/\bfred\b/i} @names;
#sum函数
my $total = sum(1..100);
#max函数
my $max = max(3,5,4,7);
#maxstr函数:最长字符串
my $max = maxstr(@strings);
#shuffle函数:对列表元素随机排序
my @shuffled = shuffle(1..1000);
List::MoreUtils模块
#none/any/all函数
if(none {$_>100} @numbers){...;}
elsif(any {$_ >50} @numbers){...;}
elsif(all {$_ <10} @numbers){...;}
#natatime函数(n at a time,同时处理n组)
my $iterator = natatime 3, @array;
#mesh函数:合并多个列表(交错填充)
my @large_array = mesh @one, @two, @three;
本文来自博客园,作者:生物信息与育种,转载请注明原文链接:https://www.cnblogs.com/miyuanbiotech/p/10962660.html。若要及时了解动态信息,请关注同名微信公众号:生物信息与育种。