Perl language entry-14-17

--------- Chapter XIV string sorting -------------------

index finds the substring

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 substring operation

#第二个参数:起始位置,第三个参数:截取长度
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 format string

Printf is different from the variable assigned to it

my $date = sprintf "%4d %02d",$yr,$mo; 
my $money = sprintf "%.2f",2.3456;

Sequence

#数组排序
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,可进行多级排序

------- Chapter XV smart match and given-when the structure ------------

Smart match operator ~~

Will be based on the number of sides of the operation mode automatically determine what type of data comparison and matching, generally independent of the longitudinal sequence, in special circumstances.

say "I found fred in the same" if $name ~~ /Fred/;

Different processing operands:

%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 #数组是否相等

Example 1: fred keys% names match, the printing if

#传统写法:
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

Example 2: determining whether two identical arrays of equal length

#传统写法:
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 the statement
    given-when many conditions, similar to the c language switch statement.
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 a plurality of matching entries

Will be given into the foreach loop test

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"}
}

---------- ---------------------- Chapter XVI Process Management

system function

perl program the parent process, system for the child process.

#一般就是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;

Environment Variables

%ENV : 每个键都代表一个环境变量  
$ENV{'PATH'} = "/home/rootbeer/bin:$ENV{'PATH'}";

Other types of system functions and commands

#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函数

------ Chapter XVII advanced Perl skills -------------------

slice

#标量:
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"; #也能内插

Capture error

  • eval expression
    checks to fatal errors immediately stop operation of the entire eval block, the rest of the code continues to run after exiting.
    The default block returns the last expression results statement. If the error is captured, the entire statement block returns undef, and an error message in the special variable $ @.
#如对除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操作符

Advanced error handling

Perl language processing error basic approach: a die throw, catch the exception using eval, $ @ by identifying the error message to determine where the problem is.

#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 function processing list elements

Return true or false value

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 function handles list of elements

Actual results returned

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;

List of other processing elements function

Perl comes List :: Util module

#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 module

#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;

Guess you like

Origin www.cnblogs.com/jessepeng/p/10962660.html