Perl Overview



Perl coding tips

打开pipe或者访问文件的时候,最好使用die

open FILE, "a_file" or die "Can not open file a_file: $!";
close FILE;

比die更好用的是croak

use Carp;
a("a_file"); #resume that a_file does exist
a("b_file"); #resume that b_file does not exist
sub a {
      my $filename = shift;
      open FILE, "$filename" or croak "Can not open file $filename: $!";
      return 0;
}

用dumper来print复杂的数据结构,便于debug

use Data::Dumper;

$var = {"name" => "hello", "action" => "speak" };
print Dumper($var);

用grep和map可以节省很多代码

my @foos = grep {!/^#/} @bars;    # weed out comments

my %hash = map {  lc($_) => 1  } @array

my @squares = map { $_ * $_ } grep { $_ > 5 } @numbers;

使用qq代替双引号,使用q代替单引号,list赋值使用qw

$a = qq{"}; #{} is used for boundary
$b = qq!"!; #!! is the same

$c = q{'};
@vars = qw{a b c};

使用list的内置函数,不要重新发明轮子

use List::Util qw(max);

my @vars = qw(1 2 3);
my $result = max(@vars);

打印多行的信息

$a = "hello";
print <<ENDOFPRINT;
Dear Lee,
    blablabla...
    $a
ENDOFPRINT

$b = <<ENDOFA;
Dear friend,
   I am here.
ENDOFA

只想做语法检查

perl -cwT test.pl

查看Perl默认的include路径

perl -e "print join(qq{\n}, @INC);"

使用自己的local路径下的库

use lib '/home/xx/eda_scripts/pm';

查看perl的pod格式的说明

perldoc rvp.pm
perldoc perldoc

Perl5.8之后的版本,可以在数据中间加下划线

$a = 111_222;
print "a = ", $a , "\n";

调用其他shell命令,同时获得shell命令的STDERR以及STDOUT信息

$pid = open $readme, "-|", "$cmd 2>&1";
while (<$readme>) {
    push(@out, $_);
}
close $readme;

Perl使用子线程,获得子线程的STDERR信息

pipe(READER, WRITER) or die "pipe no good: $!";
my $pid = fork();
die "Can no fork: $!" unless defined $pid;
if($pid) { #parent process
    close WRITER;
    while(<READER>) {
	push @out, $_;
    }    
}
else { #child process
    close READER;
    open STDERR, ">&WRITER";
    $parser = XML::LibXML->new;
    $parser->validation(1);
    exit 0;
}

多线程

因为fork是复制出一个完全一样的进程,所以“go on”会被print 2 次。

 my $pid = fork();
 if($pid) {
     #parent
     print "in parent\n";
 }
 else {
     #child
     print "in child\n";
 }
 print "go on\n";

child process中途退出了,所以 “go on”只被print 1次

 my $pid = fork();
 if($pid) {
     #parent
     print "in parent\n";
 }
 else {
     #child
     print "in child\n";
     exit;
 }
 print "go on\n";

child process通过exec,替换掉当前process,所以 “never print this”不会被print

  my $pid = fork();

  if($pid) {
      #parent
      print "in parent\n";
  }
  else {
      #child
      print "in child\n";
      exec("ls");
      print "never print this.\n";
  }
  print "go on\n";

eval{}是一种保护性写法。eval的运行结果放在$@里。可以结合alarm handler来完成很多应用

  print STDERR "type your password: ";
  my $password =
  eval {
  local $SIG{ALRM} = sub { die "timeout\n" };
  alarm (5); # five second timeout
  return <STDIN>;
  };
  alarm (0);
  print STDERR "you timed out\n" if $@ =~ /timeout/;

reaper函数,非阻塞式(WNOHANG)的处理所有子进程,$kid等于-1的时候,表示没有需要回收的进程,跳出reaper函数

  use POSIX 'WNOHANG';
  $SIG{CHLD} = \&reaper;
  sub reaper {
      while ((my $kid = waitpid(-1,WNOHANG)) > 0) {
      warn "Reaped child with PID $kid\n";
      }
  }

reference

类似c语言的指针

 @vars = ();
 $vars_ref = \@vars;

 $a_href = {};
 $b_href = { "name" => "b", "action" => "speak", };
 $c_href = {%{$b_href}};


 $tmp = "name";
 print $c_href->{$tmp}, "\n"; #This is called a symbolic reference

安装module

 cpan install Template
 cpan install XML::Rabbit

Perl 在验证中的应用

Perl 参考网站