Learning Perl 2-debugoo
1.子程序1).创建子程序:使用关键字sub
sub marine {
print "Hello, world\n";
}
calling subroutines,使用&号
&marine
(2).返回值:所有的子程序最后一个表达式的运算结果都当作返回值。所以子程序只有“”有用返回值“和无用返回值之分。所以让一个类似print的函数的结果来充当返回值十分糟糕。比较合适的是最后一行有个if分支。
(3).参数
调用的时候加上列表表达式就行。例如&max(10, 15)。多余的变量都会被忽略,超过数组@_边界的变量将会是undef。
Perl在子程序中用@_数组存储参数。第一个参数是$_,第二哥存储在$_...
注意:这些变量仅是数组@_的一部分,与标量$_无关。这和任意变量$arr与@arr,$arr无关的道理一样。
sub max {
if($_ > $_) {
$_;
} else {
$_;
}
}
@_是子程序的私有变量,如果有了一个全局变量@_,调用前会先被存起来,并在子程序返回时恢复原本的值。
(4).Perl子程序的参数的传递是按引用传。
#!/usr/bin/perl -w sub marine{ $_="sub1"; $_="sub2";} $m="out1";$n="out2";print marine($m,$n)."\n";print "$m\n$n";则会输出sub2sub1sub2(5).由于perl的子程序参数是可变长度的参数列表,可以用if来检查if(@_ != 2) {print "WARNING, this subroutine should get exactly two parameters!\n"}块的最后一条语句可以省略;号。无论在控制结构的块还是在子程序的块中。(6).return $_;立即返回某个值。(7).何时可以省略调用子程序时的&:当定义在调用之前,或者用()来传递参数时就可以省略&(8).返回非标量值,最后一行为列表即可sub marine{#...reverse 1..10;}(9).采用高水位标记算法来处理任意数量参数的maxprint &max(3,5,6,1,2,12);#或者直接传入一个列表#@numbers=(3,5,6,1,2,12);#print &max(@numbers);sub max { my($max_so_far)=shift @_; foreach (@_) { if($_ > $max_so_far) { $max_so_far=$_ } } $max_so_far}2.perl范围声明our,"把名字限于某个范围“,其实就是明确声明一个"全局变量",虽然是在某个模块或者函数里面定义的,外面的也可以访问,如果已经声明过了,再次用"our",表示此处用的是全局的那个,不是同名的私有或者局部变量 our $PROGRAM_NAME = "waiter";{my$PROGRAM_NAME = "something";our $PROGRAM_NAME = "server"; #这里的our和外面的相同,和前句不同。# 这里调用的代码看到的是"server"}# 这里执行的代码看到的仍然是"server". my ,"把名字和值都限于限于某个范围",简单说,就是只能本层模块或者函数可以看到这个变量,高一层的或者低一层的都看不到的。sub greeting1{ my ($hello) = "How are you do?"; greeting2();} sub greeting2{ print "$hello\n";}$hello = "How are you doing?";greeting2();greeting1();greeting2();运行结果:How are you doing?How are you doing?How are you doing?--------------------------一个 How are you do? 都没有,在greeting1中call greeting2时,greeting2看不到greeting1的私有 $hello变量,只能看到外面的全局变量$hello local,"把值局限于某个范围",也有叫"动态词法范围",有点不好懂。我的理解,就是本层和本层下层的函数可以看到本层的变量,但是本层上一层的不可以。到底范围是多少,不仅取决于本层的函数,还要看下一层的程序长度和深度,所以叫"动态范围"。sub greeting1{ local ($hello) = "How are you do?"; greeting2(); }sub greeting2{ print "$hello\n";}$hello = "How are you doing?";greeting2();greeting1();greeting2();运行结果:How are you doing?How are you do?How are you doing?-----------------------跟用 my 时不一样了吧? 此时在greeting1调用greeting2时,greeting2可以看到greeting1的局部变量$hello,外部的全局变量当然就隐藏了。 范围操作符不会改变变量赋值时的上下文。例如my($num)=@_;#列表上下文,等同于($num)=@_,$num是第一个元素的值my $num=@_;#标量上下文,等同于$num=@_,$num是列表的长度 3. 使用use strict;强制使用一些良好的程序规范,例如不能操作未初始化的变量。可以有效防止变量名打错的情况。 4. 钻石操作符钻石操作符是perl的读取文件(文件名通过参数传入,即@ARGV数组。如果@ARGV为空,则改用标准输入流)每一行的操作符,让perl程序也能像cat,sed等应用程序直接处理文本文件。是一个整行输入操作符的特例。#!/usr/bin/perl -w while (defined ($line=)){ chomp ($line); print "$line\n";}或者简写成while () {chomp;print "$_\n";} print; cat 的perl实现,print sort; sort的perl实现 的另一个例子,通过打开的文件描述符open(HANDLE,"c:/test.txt") or die "文件不能打开"; while () #注:这就是对文件句柄读取一行并存入变量 $_ { print; #注:打印变量 $_ } 5.输出至标准输出print注意:print (2+3)*4;会打印5,然后print的返回值1(成功)会被乘以4. 小心这种带括号的操作符用法。printf和C语言的printf类似,%g是输出恰当的数值形式。自动输出整数,浮点数和指数形式。例如5/2, 51**17会输出2.5,1.0683e+29生成格式字符串my @items=qw(wilma dino pebbles)my $format="The items are:\n".("%10s\n" x @items)#使用x来复制字符串,@items为3,即“%10s\n”三遍printf $format, @items 6.文件句柄(1).打开文件句柄通常文件句柄用大写标识。Perl提供3种文件句柄:STDIN STDOUT STDERR由Perl的父进程(可能是Shell)提供。当使用其他的文件句柄时,使用open操作符告诉Perl。例如: open CONFIG,"dino"open CONFIG,"fred"#如果已经有一个文件存在,则清楚原有内容并以新内容取代之open LOG,">>LogFile"#如果不存在,则创建。如果存在,则追加检测文件句柄的有效性my $success=open LOG,“>>logfile”unless ($success) {#open失败}比如可以直接使用die中止运行或者warning送出警告信息。perl程序的exit status:0成功,1语法错误,2处理某程序发生错误,3可能找不到某个细节配置文件等if(!open LOG, ">>logfile") {warning "can not create file"}if(@ARGV < 2)die "Not enough arguments.\n"另:open CONFIG, "logfile" or die "not such file";关闭文件描述符:close LOG (2).使用文件句柄print LOG “...”;printf STDERR "...";open PASSWD, "/etc/passwd"or die "cannot open passwd file"while () {chomp;......}或者放到列表里open PASSWD, '
页:
[1]