函数:
sub关键字用于定义函数
sub function_name
{
do_something;
}
调用函使用符号& ampersand
&function_name;
函数的返回值初步
通常返回代码块中最后执行语句的值。
例如:
sub list_from_fred_to_barney {
if ($fred < $barney) {
# Count upwards from $fred to $barney
$fred..$barney;
} else {
# Count downwards from $fred to $barney
reverse $barney..$fred;
}
}
$fred = 11;
$barney = 6;
@c = &list_from_fred_to_barney; # @c gets (11, 10, 9, 8, 7, 6)
如果最后一行是print一类语句,返回值为1,表示调用成功,返回false表示失败。
还有更多复杂的情况。
函数参数
在函数中, @_为参数数组列表,或使用$_[index]访问任意一个参数。
在Perl中函数可能修改参数的值,例如:
$A = 1;
$B = 2;
sub switch{
($_[0],$_[1])=($_[1],$_[0]);
}
print $A."/n".$B."/n";
&switch($A,$B);
print "After switch/n";
print $A."/n".$B."/n";
输出:
1 2
After switch
2 1
定义私有变量Lexical Variables:关键字my
create private variables called lexical variables at any time with the my operator
sub max {
my($a, $b)=@_; # give names to the parameters
if ($a > $b) { $a } else { $b }
}
被关键字my修饰的变量仅在代码块中有效.
local关键字,在函数中用local修饰的全局变量,local变量在函数代码块中的值在调用其他函数时有效,但离开这个函数代码块后就不再有效。例子:
$office = "global"; # Global $office
sub say { print "$office/n"; } # print the currently visible $office
sub fred { local($office) = "fred"; &say( ); }
sub barney { my($office) = "barney"; print $office."/n";&say( ); }
&say( ); # says "global", accessing $office directly
&fred( ); # says "fred", dynamic scope,
# because fred's local $office hides the global
&barney( ); # says "global", lexical scope;
输出: # barney's $office is visible only in that block
global 显示全局变量的值
fred 全局变量在fred中被修改并显示,但退出函数fred后全局变量office会恢复原有的值
barney 局部变量office的值是barney
global 在say函数中可见的只有全局变量office
变长参数名,支持变长参数的最大值函数:
$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;
}
use strict; 选项
在perl中对于变量的使用非常随意,因此变量名输入错误可能带来严重后果(输入错误的变量名会被误认为新变量)
当使用use strict;后源代码中所有的新变量声明都必须以my关键字开头,不使用my关键字而使用新变量名会造成一个编译错误.
编写perl程序时强烈建议使用这个选项.
return 操作符,从函数中返回值或表达式
当表达式或值本身就是函数最后执行的语句时,return操作符不是必须的.
&操作符在不引起函数调用歧义的情况下也不是必须的,只要系统中没有定义相同名称的函数即可.
Perl数组大小过大的性能隐患:
sub total{
my $total = pop @_;
foreach (@_){
$total+=$_;
}
$total;
}
print total(1..1e7);
这个简单的累加函数会导致Perl解释器占用300MB以上的内存,系统反应类似死机,使用大数组要谨慎.
Hash 哈希
一个哈希表是由keys和values组成的数据对集合.
其中keys和values都是任意标量,
keys总是字符串,如果使用数学表达式作为key,它将会被计算出来并存储为字符串.例如如果key是50/20,那么会被保存为字符串"2.5"
keys在一个hash结构中是唯一的.
访问hash表中的value
$hash{$some_key} curly braces
对于哈希键与值的关系可以通过以下方法理解
"the family_name of fred is flintstone". So the hash is named family_name. Then it becomes clear what the relationship is between the keys and their values.
hashtable of Key is Value.
作为整体的hash表使用% percent sign 访问.
hash表可以和键-值对的数组相互转换
%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
"wilma", 1.72e30, "betty", "bye/n");
@any_array = %some_hash;
在这种过程中,键和值的顺序是任意的.
可以通过%new_hash = %old_hash; 拷贝hash表
常用用法
%inverse_hash = reverse %any_hash;
逆序一个hash表的意义,是将键-值对 变成了值-键对,这是一种非常常用的用法
%inverse_hash 中的键是%any_hash中的值
如果%any_hash中的值不唯一,%inverse_hash中该键的值可能对应在%any_hash中的任何一个匹配的键.(而不会警告或出错)
使用=>匹配键值对,简单地替换comma , 即可
%last_name = (
"fred" => "flintstone",
"betty" => "rubble",
);
keys/values 函数
用于对%hash进行操作的函数
keys 返回包含所有key的数组,values 返回包含所有value的数组
注意在标量上下文中,返回的实际上是key的总数,例如:
my $count = keys %hash; # gets a number of key-value pairs
当把%hash当作布尔值使用,例如:
if(%hash)
当%hash至少含有一个键-值对时,结果为真.
each 函数, 返回一个键-值对,通常用法:
while ( ($key, $value) = each %hash ) {
print "$key => $value/n";
}
当each遍历完所有元素会返回一个空数组,此时跳出循环.
可以将each看作一个简单的迭代器.
有很多情况会导致each迭代器被重置,例如使用了keys或values函数,在each遍历中增加键-值对不一定会重置each,最好不要这样做!!!仅仅使用each作为遍历(只读)的工具.
对于嵌套的迭代器each,每个%hash有其自己的迭代元,不会混淆.
exists 函数
检验一个给定的key是否存在于hash表中
if (exists $books{"dino"}) {
print "Hey, there's a library card for dino!/n";
}
<STDIN>在foreach和while循环中的不同
在while循环中使用默认变量$_
while (<STDIN>) {
print "I saw $_";
}
打印每条输入(包含换行符)
使用foreach循环完成同样的工作
foreach (<STDIN>) {
print "I saw $_";
}
这里有着细微的不同,在while循环中,每次读取<STDIN>的一行,然后进入循环处理.而foreach循环中,<STDIN>被用在一个数组语境中,因此在运行循环体之前,必须读取完<STDIN>所有的内容,在处理大文件和大输入的时候,使用while能取得更好的效能(一次处理一行),因此,只要可能,就使用while,而非foreach
Diamond operater <>
对于大量Unix工具,cat或sed 使用连字符hyphen - 代表标准输入
例如: fred- betty表示:文件fred 标准输入 文件betty
while (<>) {
chomp;
print "It was $_ that I saw!/n";
}
读取参数作为输入并打印
注意<>用于处理输入,而输入的每一行被依次放入了$_变量
标准输出 print
print @array; #依次打印数组中元素,不留空格
print "@array"; #依次打印数组中元素,元素之间有空格
如果@array的元素是以换行结尾的字符串,在双引号内的@array打印时还是会加上空格,看起来第一行之后的行有一个空格的缩进.最好用chomp处理一下
print后面的参数是数组语境,使用<>用于数组语境时,得到的是一个由每行字符串组成的数组,因此可以这样使用
print <>; #与cat命令使用方式相同
print sort <>; #与sort命令使用方式相同
@ARGV 参数字符串
在程序开始之前,@ARGV数组被初始化为由参数填充的数组
<>在@ARGV中查找需要的参数,因此可以人为初始化@ARGV数组
@ARGV = qw# larry moe curly #; #读取这三个文件,无论调用参数为何
while (<>) {
chomp;
print "It was $_ that I saw in some stooge-like file!/n";
}