Perl的发明人:Larry Wall。
Perl”,指语言本身;“perl”,指程序运行的解释器。
#!/usr/local/bin/perl -w print "Hello,world!/n";
在Unix系统中,如果文本的第一行前两个字符是“#!”,接着的就是执行下面文件的程序。perl在你的系统的哪里,可以用which 或者whereis来查找。一般都在/usr/bin/perl或者/usr/local/bin/perl这两个地方。-w表示开启警告。
$ perl -w perl程序 # 命令行执行警告 #!/usr/bin/perl -w # 源代码中使用警告
Perl通常允许使用任意数量的空白(如空格,制表符,换行符)来使程序易于阅读。 Perl中没有“main”程序。 Perl中不需要声明变量。 Perl严格区分大小写。 Perl中的括号可以省略。 Perl中所有数字内部的格式都是双精度浮点数。
浮点数
1.25 -12e-24 #- -12x10 的-24 次方(很小的负数) -1.2E-23 #指数符号可以大写(E)整数
-40 61298040283768#为方便阅读可作:61_298_040_283_768非十进制整数
0377 #八进制数字 377,等同于十进制数字 255 0xff #十六进制数字 FF,等同于十进制数字 255 0b11111111 #等同于十进制数字 255数字操作符
2+3 #2+3,5 5.1-2.4 #5.1-2.4,2.7 3*12 #3*12,36 14/2 #14/2,7 10.2/0.3 #10.2/0.3,34 10/3 #通常是浮点除,3.33333... ...
单引号字符串
'fred' #四个字符:f,r,e,d '' #空字符(没有字符) 'hello\n' '\'\\' #单引号(')跟着反斜线(\)字符串 单引号中的 "\n" 不会被当作换行符来处理。双引号字符串
"barney" #等同于 'barney' "hello world\n" #hello world,换行
变量由符号($)后接 Perl 标识符构成。Perl大小写是严格区分的:变量$Fred 和变量$fred是不同的。
$fred = 17; $barney = "hello";
defined 函数
能返回 undef 的操作之一是行输入操作,<STDIN>。通常,它会返回文本中的一行。 但如果没有更多的输入,如到了文件的结尾,则返回 undef。要分辨其是 undef 还是空串,可以使用 defined 函数, ,如果其参数是 undef 值就返回 false,其他 值返回 true。$madonna = <STDIN>; If ($defined ($madonna)){ print "The input was $madonna"; } else { print "No input available!\n; }如果想声明自己的 undef 值,可以使用 undef:
$madonna = undef ; #同$madonna 从未被初始化一样。
"hello"."world" # 同于 "helloworld" "hello".''."world" # 同于 "hello world" 'hello world'."\n" # 同于 "hello world\n"重复操作符 "x"
"fred" x 3 # "fredfredfred" 5 x 4 # 等于 "5" x 4, "5555"
"12" * "3" # * 操作符需要数字,所以结果为 36 "12fred34" * " 3" # 结果仍然是 36 , 后面的非数字部分和前面的空格都过滤掉。 "Z" . 5 * 7 # 等于 "Z".35, 或 "Z35"
$fred+=5; $barney*=3; $str .= "";
比较关系 | 数字 | 字符串 |
相等 | == | eq |
不相等 | != | ne |
小于 | < | lt |
大于 | > | gt |
小于等于 | <= | le |
大于等于 | >= | ge |
if ($name gt 'fred') { print "$name’comes after 'fred' in sorted order.\n"; }
$count = 0; while ($count < 10) { $count + = 2; print "count is now $count\n"; }
print "hello world\n"; #输出 hello world,后接换行符 print "The answer is", 6*7, ".\n"; #其实是列表【变量内插】字符串中引用标量变量。变量内插通常也叫做双引号内插,因为它在双引号中(而非单引号)才有效。
$meal = "brontosaurus steak" ; $barney = "fred ate a $meal"; $barney = 'fred ate a'.$meal; # 同上 $fred =‘hello’; print“The name is\$fred .\n”; #打印出美圆符号,变量不会被其值替换 print‘The name is $fred’. “\n”; #同上
【使用花括号】
$what =“brontosaurus steak”; $n = 3; print“fred ate $n $whats.\n”; #不是steaks,而是$whats的值 print“fred ate $n ${what}s.\n”; #现在是使用变量$what print“fred ate $n $what”. “s.\n”; #另一种方法 print‘fred ate ’. $n . ‘’. $what . “s.\n”; #一种复杂的方法
$text = "a line of text\n"; # 也可以由<STDIN>输入 chomp($text); #去掉换行符(\n)。一步执行:
chomp ($text = <STDIN>); #读入,但不含换行符chomp 是一个函数。作为一个函数,它有一个返回值,为移除的字符的个数。这个数字基本上没什么用:
$food = <STDIN>; $betty = chomp $food; #得到值 1
如上,在使用 chomp 时,可以使用或不使用括号()。这又是 Perl 中的一条通用规则:除非移除它们时含义会变,否则括号是可以省略的。
#!/usr/bin/env perl -w $fred[0] = "yabba"; $fred[1] = "dabba"; $fred[2] = "doo"; print @fred; #print @fred."\n";
#对于列表(“fred”, “barney”, “betty”, “wilma”, “dino”) qw( fred barney betty wilma dino ) #同上,但输入更少 qw ! fred barney betty wilma dino ! qw# fred barney betty wilma dino # #有些像注释
($fred, $barney, $dino) = ("flintstone", "rubble", undef); ($fred, $barney) = qw <flintstone rubble slate granite>; #两个值被忽略了 ($rocks[0],$rocks[1],$rocks[2],$rocks[3]) = qw/talc mica feldspar quartz/;当想引用这个数组时, Perl 有一种简单的写法。在数组名前加@(后没有中括号) 来引用整个数组。 你可以把他读作 "all of the "(所有的)”,所以@rocks 可以 读作 "all of the rocks(所有的石头)"。其在赋值运算符左右均有效:
@rocks = qw / bedrock slate lava /; @tiny = (); #空表 @giant = 1..1e5; #包含 100,000 个元素的表 @stuff = (@giant, undef, @giant); #包含 200,001 个元素的表 @dino = "granite"; @quarry = (@rocks, "crushed rock", @tiny, $dino);
@array = 5..9; $fred = pop(@array); #$fred 得到 9,@array 现在为(5,6,7,8) $barney = pop @array; #$barney gets 8, @array 现在为(5,6,7) pop @array; #@array 现在为(5,6)(7 被丢弃了) push(@array,0); #@array 现在为(5,6,0) push @array,8; #@array 现在为(5,6,0,8) push @array,1..10; #@array 现在多了 10 个元素 @others =qw/9 0 2 1 0 /; push @array,@others; #@array 现在又多了 5 个元素(共有 19 个)
@array = qw# dino fred barney #; $m = shift (@array); #$m 得到 "dino", @array 现在为 ("fred", "barney") $n = shift @array; #$n 得到 "fred", @array 现在为 ("barney") shift @array; #@array 现在为空 $o = shift @array; #$o 得到 undef, @arry 仍为空 unshift(@array,5); #@array 现在为(5) unshift @array,4; #@array 现在为(4,5) @others = 1..3; unshift @array, @others; #array 现在为(1,2,3,4,5)和 pop 类似,如果其数组变量为空,则返回 undef。
@rocks = qw{ flintstone slate rubble }; print "quartz @rocks limestone\n"; #输出为 5 种 rocks 由空格分开
foreach $rock (qw/ bedrock slate lava /) { print "One rock is $rock.\n" ; #打印出 3 种 rocks }这里的$rock不是这些列表元素中的一个拷贝而是这些元素本身
foreach(1..10){ #使用默认的变量$_ print "I can count to $_!\n"; } $_ = "Yabba dabba doo\n"; print; # 打印出默认变量 $_
@fred = 6 .. 10; @barney = reverse (@fred); #得到 10,9,8,7,6 @wilma = reverse 6 . .10; #同上,没有使用额外的数组 @fred = reverse @fred; #将逆转过的字符串存回去
@rocks = qw/ bedrock slate rubble granite /; @sorted = sort(@rocks); #得到 bedrock, granite, rubble, slate
sub marine { $n + = 1; #全局变量$n print "Hello, sailor number $n!\n"; }
&marine; #输出 Hello, sailor number 1! &marine; #输出 Hello, sailor number 2!由于所有的被调用的子程序都要返回值,因此使用特殊的返回值语法在大多数情况下是一种浪费。因此Larry 将之简化了。
$n = &max(10,15); # 此子程序有 2 个参数此参数列表被传到子程序中;这些参数可以被子程序使用。当然,这些参数存放在某个地方,在 Perl 中,会自动将此参数列表(此参数列表的另一个名字)自动存放在 一个叫做@_的数组中。子程序可以访问次数组变量来确定此参数的个数以及其值。 这也就是说此子程序参数的第一个值存放在$_[0]中,第二个存放在$_[1],依次类 推。但必须强调的是这些变量和 $_ 这个变量没有任何关系,如$dino3(数组 @dino 的一个元素)和$dino 的关系一样。这些参数必须存放在某个数组变量中, Perl 存放在@_这个变量中。
$n = &max(10,15); #此子程序有2 个参数 sub max{ if($_[0] > $_[1]) { $_[0]; } else { $_[1]; } }
foreach (1..10){ my($square) = $_*$_; #本循环中的私有变量 print "$_ squared is $squrare.\n"; }变量$square 是私有的,仅在此块中可见;在本例中,此块为 foreach 循环块。
my ($num) = @_; # 列表 context, 同($sum) = @_; my $num = @_; # 标量 context, 同$num = @_;任意参数版本:
$maximum = &max(3,5,10,4,6); //本程序就可以使用任意多个参数 sub max { my($max_so_far) = shift @_; foreach (@_){ if($_>$max_so_far){ $max_so_far=$_; } } $max_so_far; //最后一次计算的默认作为返回值 }
$hash {$some_key}作为整体的 hash
从标准输入设备输入是容易的。使用<STDIN>。在标量 context 中它将返回输入的下一行:
chomp($line=<STDIN>)由于行输入操作在到达文件的结尾时将返回 undef,这对于从循环退出时非常方便的:
while (defined($line = <STDIN>)) { print "I saw $line"; }
#!/usr/local/bin/perl -w @lines = `perldoc -u -f atan2`; foreach (@lines) { s//w<([^>]+)>//U$1/g; print; }
#!/usr/bin/perl @filename_list=("../tracing023/hadoop-hadoop-jobtracker-tracing023.log","../tracing023/hadoop-hadoop-namenode-tracing023.log","../tracing017/hadoop-hadoop-datanode-tracing017.log","../tracing016/hadoop-hadoop-datanode-tracing016.log","../tracing019/hadoop-hadoop-datanode-tracing019.log","../tracing020/hadoop-hadoop-datanode-tracing020.log","../tracing017/hadoop-hadoop-tasktracker-tracing017.log","../tracing016/hadoop-hadoop-tasktracker-tracing016.log","../tracing019/hadoop-hadoop-tasktracker-tracing019.log","../tracing020/hadoop-hadoop-tasktracker-tracing020.log"); $savefile="./mapAndReduce.result"; &rw($filename,$savefile); sub rw{ my %map; my %map_id_time; #list the ids in jobtracer-tracing017 my %map_ids; open(IN,$filename_list[0]); foreach(@lines=<IN>) { if($_=~/^(.*? .*? ).*Adding task \(REDUCE\) '(attempt_.*?)('| |$|,|\/)/) { if(!exists $map_ids{$2}) { $map_ids{$2}=1; } } } close IN; #output the list to file open(OUT,">ids.result"); foreach(keys %map_ids) { print OUT $_."\n"; } close OUT; #analyze all the files based on map_ids foreach(@filename_list) { my $filename=$_; my %tmp_map; open(IN,$filename); foreach(@lines=<IN>) { if($_=~/^(.*? .*? ).*(attempt_.*?)('| |$|,|\/)/ && exists $map_ids{$2}) { if(!exists $tmp_map{$2}) { $tmp_map{$2}="\n---------[LOG:".$filename."]---------\n"; } $tmp_map{$2}.=$_; if(!exists $map_id_time{$2}) { $map_id_time{$2}=$1; } } } foreach(keys %tmp_map) { $map{$_}.=$tmp_map{$_}; } close IN; } open(OUT,">".$savefile); my @list_time_id; my $index=0; foreach(keys %map_id_time) { $list_time_id[$index][0]=$map_id_time{$_}; $list_time_id[$index][1]=$_; $index++; } my @sort_list_time_id=sort {$a->[0] cmp $b->[0]} @list_time_id; #@blk_list2=sort {$a cmp $b} @blk_list; for(my $i=0;$i<$index;$i++) { #print $sort_list_time_id[$i][0]."\n"; my $tmp_id=$sort_list_time_id[$i][1]; print OUT "\n/***********".$tmp_id."**********/\n"; print OUT $map{$tmp_id}; print OUT "\n"; } close OUT; }