注释
=pod
1.xxx
2.ddd
3.这是多行注释
=cut
#this is comment 单行注释
循环语句
while
$i = 1;
while($i < 10){
print $i."\n";
$i += 1;
}
while ... continue...
my $i = 1;
while($i < 5) {
say $i;
} continue {
$i++;
}
until
my $i = 1;
until($i >=5 ) {
say $i;
$i++;
}
while(condition) == until(! condition)
do ... while ...
my @a = (1 .. 10);
my $i;
do {
$i = shift @a;
say $i;
} while ($i < 5);
Perl 中没有 do 。。。while。。。循环语句, 实际上这是do语句与while语句一起工作。
for
for($i=1; $i<=9; $i++){
for($j=1; $j<=$i; $j++){
print "$j*$i=".($i*$j)."\t";
}
print "\n";
}
foreach
@list = (1 .. 5);
foreach my $i(@list){
print $i."\n";
}
foreach (@list){
print "$_\n";
}
each
my %array = (
"a" => "1",
"b" => 2,
"c" => 3,
);
while(my($index, $val) = each(%array)){
print "$index:$val\n";
}
if ... elsif ... else
my @array = (1..10);
foreach (@array){
if($_ == 1) {
print "This is one($_)\n";
}elsif($_ == 2){
print "This is two($_)\n";
}else{
print "$_\n";
}
if($_ > 5){
last;
}
}
unless ... else ...
my $i = 1;
unless($i > 5){
say "$i is not larger than 5";
}else {
say "$i is larger than 5";
}
if(condition) == unless(! condition)
grep And map
my @UpCase = ("A" .. "Z");
say join('_', map lc, @UpCase);
say join('_', map chr, (65 .. 90));
say join(', ', (grep {$_ > 15} (10 .. 20)));
执行结果如下:
a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z
A_B_C_D_E_F_G_H_I_J_K_L_M_N_O_P_Q_R_S_T_U_V_W_X_Y_Z
16, 17, 18, 19, 20
@_ all params list
$maximum = &max(3, 5, 10, 7, 4, 2);
sub max{
my $max_val = shift @_;
foreach(@_){
if($max_val < $_){
$max_val = $_;
}
}
return $max_val;
}
print $maximum;
Array
@array = (1,2,3,4,5,6,7,8,9);
for $num(@array){
$num % 2 && print $num."\t";
}
@array2 = (1..10);
print $array2[$#array2];
my $fred = "abcd";
my @fred = undef;
$fred[0] = "0";
$fred[1] = "1";
$fred[9] = "9";
print $fred[1];
my $a;
my $b;
my $c;
($a, $b, $c) = (1, "abc", undef);
print $a;
#交换2个变量的值
($a, $b) = ($b, $a);
print $b;
my @x = (1..10);
my @y = @x; #将数组x 复制到 数组y
@y[0] = 5;
print $x[0]; #还是1
my @temp = (1..10);
my $p1 = pop(@temp);
my $p2 = pop(@temp);
print "$p1, $p2\n"; #输出 10, 9
print "@temp"; #输入 1 2 3 4 5 6 7 8
print "\n";
push(@temp, 'a');
push(@temp, 'b');
print "@temp"; #输出 1 2 3 4 5 6 7 8 a b
$p1 = shift(@temp);
$p2 = shift(@temp);
print "$p1, $p2\n"; #输出 1, 2
print "@temp"; #输出 3 4 5 6 7 8 a b
print "\n";
unshift(@temp, 'y');
unshift(@temp, 'x');
print "@temp"; #输出 x y 3 4 5 6 7 8 a b
print "\n";
my @strs = qw(a b c d e f);
my @removed = splice(@strs, 2);
print @removed; #输出 cdef
print "\n";
print @strs; #输出 ab
$_ : each param
for(@array){
print $_."\t";
}
<pre name="code" class="plain">$_ = "aaa";
print; #输出aaa
qw (quoted, word 加上引号的单词,用空白圈引)
my @s = qw(a b c d e f);
for $i(@s){
print $i."\t";
}
my @b = qw {
/sbin
/usr/sbin
/usr/local/sbin
};
print $b[0];
Hash
#my %map = ("dog", "1", "cat", "2", "fish", "3");
my %map = (
"dog" => '1',
"cat" => '2',
"fish" => '3'
);
print $map{'dog'};
my @animals = keys %map;
foreach my $i(@animals){
print $i;
}
my @number = values %map;
foreach my $n(@number){
print $n;
}
while(my($k, $v) = each(%map)){
say $k.'-->'.$v;
}
#以key排序
foreach my $k (sort keys %h){
say $k;
}
my $variables = {
"apple" => {
"A" => 1,
"B" => 2,
},
"banana" => {
"X" => 24,
"Y" => 25,
},
};
print $variables->{"apple"}->{"A"};
文件操作
#!/usr/bin/env perl
use 5.010;
sub readFile{
my ($filepath) = @_;
say $filepath;
open FH, "<$filepath";
my @mytext = <FH>;
foreach my $text(@mytext){
#say $text;
my @line = split(":", $text);
say $line[0];
}
close FH;
}
$filepath = "passwd";
&readFile($filepath);
第二种
open my $f, "<" , "f1.pl" or die "can not open $!";
while(<$f>){
print $_;
}
close $f;
写文件
sub f1 {
open(F, ">a.txt") or die "can't open $!";
print F "123456789\n";
close F;
}
正则表达式
元字符
元字符,点(.)是通配符,匹配任何单个字符,但不包括换行符("\n")。如果要匹配(.) 则需要\.
量词
? 出现0或1次
* 出现0或多次
+ 至少出现1次
/fe+d/ 能匹配fed, feed
/go*d/ 能匹配gd,god, good, goood
/wo?d/ 能匹配wod, wd
分组
分组用括号()来表示, /(fred)+/ 能匹配 fredfred, fred 这样的字符串
选择符
用竖线(|)来表示,匹配左边或者右边。 /fred|barney|barney/,匹配出现fred,或者barney,或者betty的字符串。
字符类
字符类,是方括号[]中的一列字符,匹配括号内任意单个字符。
\d 表示 [0-9] #digit
\w 表示 [A-Za-z0-9_] #word
\s 表示 [\f\t\n\r] #空白字符(whitespace), 由格式符(form-feed), 制表符(tab), 换行符(next), 回车符(return)。
字符类的补集
\D 表示[^\d] #非数字
\W 表示[^\w]
\S 表示[^\s] #非空白字符
[\d\D] 表示匹配所有的字符 的一种通用表示法
使用m//匹配
模式放在正斜线(//)里,这是m// 的一种简写。如果要匹配的字符串中有//,我们可以用m{}, m##, m%%来代替。
如果匹配http://www.google.com, m#http://#, m{http://}, %http://%
可选修饰符
不区分大小写: /i
/yes/i 能匹配YeS
匹配任何字符:/s
点(.) 不匹配换行符,加上/s后,能匹配换行符。
添加空格: /x
/-?\d+\.?\d*/ #不方便阅读
/-? \d+ \.? \d* /x #要好一点,这里的空白被忽略。
锚定
^表示开头进行匹配
$表示结尾进行匹配
/^fred$/,能同时匹配 "fred"和“fred\n”。 在这里不关心换行符
\b 词界锚定。 /\bfred\b/ 能匹配fred,但不匹配frederick,alfred
\B 非词界锚定。 /\bsearch\B/,能匹配searches,searching,但不匹配search,researching。
绑定操作符 =~
$_ =~ /^\s$/;
sub test1{
$_ = "yabba abc ff";
if(/abc/){
say "\"/abc/\" match \"$_\""; #显示 "/abc/" match "yabba abc ff"
}
if(/abc|ff/){
say "\"/abc|ff/\" match \"$_\""; #显示 "/abc|ff/" match "yabba abc ff"
}
if(m(abc)){
say "\"m(abc)\" match \"$_\""; #显示 "m(abc)" match "yabba abc ff"
}
}
sub test2{
my $t = "123abc456xyz";
if(${t} =~ /^\d+ \w+ \d+ \w+$/x){
say "it matched!"; #能匹配
}else{
say "it does not match!";
}
}
若匹配成功 则 $&:匹配的字符串, $`: 匹配字符串之前的字符串, $': 匹配字符串之后的字符串
sub test3{
my $t = "hello world, nice to meet you!";
if($t =~ /\S(\w+),/){
say "\$&: $&"; #显示 $&: world,
say "\$`: $`"; #显示 $`: hello
say "\$': $'"; #显示 $': nice to meet you!
}
}
s/abc/xyz/ 来进行替换
sub test4{
$_ = "fred flintstone";
if(s/fred/wilma/){
say "true"; #能匹配上,显示true
}
say $_; #显示 wilma flintstone
}
sub test5{
$_ = "a b c d e f";
if(s/\s+/ /g){ #把空白字符替换成一个空格
say $_; #显示 a b c d e f
}
say $_;
}
sub test6{
$_ = "http://www.baidu.com";
if(s#http://#ftp://#){
say $_; #显示 ftp://www.baidu.com
}
}
\U 转换成大写, \L 转换成小写 $a=~模式
sub test7{
$_ = "/home/media/abc";
if ($_ =~s/(media|abc)/\U$1/gi){
say $_; #显示 /home/MEDIA/ABC
}
if ($_ =~s/(abc)/\L$1/ig){
say $_; #显示 /home/MEDIA/abc
}
}
@fileds = split /separtor/, $string;
sub test8{
my $string = "/home/media/abc/123";
my @fields = split /\//, $string;
foreach (@fields){
say $_;
};
#显示输出"", "home", "media", "abc", "123" 这5个字符串。
}
$string = join $glue @pieces;
sub test9{
my @fields = ("", "home", "media", "abc", "123");
my $string = join "/", @fields;
print $string; #输出 /home/media/abc/123
}
这不是正则表达式,这个是glob
sub test10{
my @fs = glob "*.pl";
foreach(@fs){
say "$_";
}
# 显示 1.pl, 2.pl, 3.pl
}
多线程
#!/usr/bin/env perl
use warnings;
use strict;
use threads;
use 5.010;
sub f1{
my $num = shift;
say "thread: $num started";
sleep $num;
say "done with thread $num";
return $num;
}
sub main {
my @threads;
for(my $i=1; $i<=5; $i++){
my $t = threads->new(\&f1, $i);
push(@threads, $t);
}
foreach(@threads){
my $num = $_->join;
say "done with $num";
}
}
main();
#######显示结果#########
thread: 1 started
thread: 2 started
thread: 3 started
thread: 4 started
thread: 5 started
done with thread 1
done with 1
done with thread 2
done with 2
done with thread 3
done with 3
done with thread 4
done with 4
done with thread 5
done with 5
########################
多进程
#!/usr/bin/env perl
use warnings;
use strict;
use 5.010;
sub f1 {
my $num = shift;
say "child process $num started";
sleep $num;
say "done with child process $num";
return $num;
}
sub main {
my @childs;
for(my $i=1; $i<=5; $i++){
my $pid = fork();
if($pid){ # 父进程 pid是子进程ID
push(@childs, $pid);
}elsif($pid == 0){ # 子进程
f1($i);
exit 0;
}else{
die "couldn't fork:$!\n";
}
}
foreach(@childs){
my $tmp = waitpid($_, 0);
say "done with pid $tmp";
}
}
main();
#######显示效果########
child process 1 started
child process 2 started
child process 3 started
child process 4 started
child process 5 started
done with child process 1
done with pid -10708
done with child process 2
done with pid -10900
done with child process 3
done with pid -11256
done with child process 4
done with pid -9768
done with child process 5
done with pid -10792
#######################
Module
tool/MyModule.pm
#!/usr/bin/env perl
package MyModule;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(myFun1, myFun2);
@EXPORT_OK = qw($myVar1, $myVar2);
use strict;
use warnings;
our $myVar1 = 9;
our $myVar2 = 1;
sub myFun1 {
my $N = $myVar1;
foreach my $i (1..$N) {
foreach my $j (1..$i) {
printf("%d x %d = %2d " ,$j, $i, $i*$j);
}
print "\n";
}
}
sub myFun2 {
print ++$myVar2."\n";
}
1;
main.pl
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use tool::MyModule;
sub main {
say "var1:", $MyModule::myVar1;
say "=" x 80;
$MyModule::myVar1= 5;
MyModule::myFun1();
$MyModule::myVar1= 8;
say "=" x 80;
MyModule->myFun1();
MyModule::myFun2();
MyModule->myFun2();
}
main();
OOP
Person.pm
#!/usr/bin/env perl
package Person;
use strict;
use warnings;
use 5.010;
sub new {
my $class = shift;
say("class=$class");
my $this = {};
$this->{'name'} = shift;
$this->{'age'} = shift;
bless $this, $class;
return $this;
}
sub getName {
my($this) = @_;
return $this->{'name'};
}
sub setName {
my($this, $name) = @_;
$this->{'name'} = $name;
}
sub getAge {
my($this) = @_;
return $this->{'name'};
}
sub setAge {
my($this, $age) = @_;
$this->{'age'} = $age;
}
sub toString {
my($this) = @_;
say "Hello my name is $this->{'name'}, I am $this->{'age'} years old!";
}
1;
main.pl
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use Person;
sub main {
my $p1 = Person->new("Tom", 24);
$p1->toString();
my $p3 = new Person("Jerry", 25);
$p3->toString();
my $p2 = Person::new('Person', "cooper", 28);
$p2->toString();
}
main();
Perl内部变量
$- 当前页可打印的行数,属于Perl格式系统的一部分
$! 根据上下文内容返回错误号或者错误串
$” 列表分隔符
$# 打印数字时默认的数字输出格式
$$ Perl解释器的进程ID
$% 当前输出通道的当前页号
$& 与上个格式匹配的字符串
$( 当前进程的组ID
$) 当前进程的有效组ID
$* 设置1表示处理多行格式.现在多以/s和/m修饰符取代之.
$, 当前输出字段分隔符
$. 上次阅读的文件的当前输入行号
$/ 当前输入记录分隔符,默认情况是新行
$: 字符设置,此后的字符串将被分开,以填充连续的字段.
$; 在仿真多维数组时使用的分隔符.
$? 返回上一个外部命令的状态
$@ Perl解释器从eval语句返回的错误消息
$[ 数组中第一个元素的索引号
$\ 当前输出记录的分隔符
$] Perl解释器的子版本号
$^ 当前通道最上面的页面输出格式名字
$^A 打印前用于保存格式化数据的变量
$^D调试标志的值
$^E在非UNIX环境中的操作系统扩展错误信息
$^F最大的文件捆述符数值
$^H由编译器激活的语法检查状态
$^I内置控制编辑器的值
$^L发送到输出通道的走纸换页符
$^M备用内存池的大小
$^O操作系统名
$^P指定当前调试值的内部变量
$^R正则表达式块的上次求值结果
$^S当前解释器状态
$^T从新世纪开始算起,脚步本以秒计算的开始运行的时间
$^W警告开关的当前值
$^X Perl二进制可执行代码的名字
$_ 默认的输入/输出和格式匹配空间
$| 控制对当前选择的输出文件句柄的缓冲
$~ 当前报告格式的名字
$` 在上个格式匹配信息前的字符串
$’ 在上个格式匹配信息后的字符串
$+ 与上个正则表达式搜索格式匹配的最后一个括号
$< 当前执行解释器的用户的真实ID
$<digits>含有与上个匹配正则表达式对应括号结果
$= 当前页面可打印行的数目
$> 当前进程的有效用户ID
包含正在执行的脚本的文件名
$ ARGV 从默认的文件句柄中读取时的当前文件名
%ENV 环境变量列表
%INC 通过do或require包含的文件列表
%SIG 信号列表及其处理方式
@_ 传给子程序的参数列表
@ARGV 传给脚本的命令行参数列表
@INC 在导入模块时需要搜索的目录列表