(注:本文不是原创,只是学习过程中的学习笔记.)
一.简单变量(标量变量)
基本上,简单变量就是一个数据单元,这个单元可以是数字或字符串.在PERL中,所有的简单变量都有缺省初始值:"",即空字符.但是建议给所有变量赋初值,否则当程序变得大而复杂后,很容易出现不可预料且很难调试的错误.
1.整型
整型是PERL最常用的简单变量.8进制以0打头,16进制以0x打头.
例:
$var1 = 12345;
$var2 = 047; (等于十进制的39)
$var3 = 0x1f; (等于十进制的31)
PERL实际上把整数存在计算机中的浮点寄存器中,所以实际上被当作浮点数看待,整数实为浮点数的特例.
2.浮点数
如11.4, -0.3, .3, 3., 54.1e+02, 5.41e03等,浮点寄存器通常不能精确地存贮浮点数,从而产生误差,在运算和比较中要特别注意.指数的范围通常为-309到+308.
例:
$value = 9.01e+21;
3.字符串
C程序员要注意,在PERL中,字符串的末尾并不含有隐含的NULL字符,NULL字符可以出现在串的任何位置.
双引号内的字符串中支持简单变量替换,例如:
$number = 11;
$text = "This text contains the number $number.";
则$text的内容为:"This text contains the number 11."
双引号内的字符串中支持转义字符,要在字符串中包含双引号或反斜线,则在其前加一个反斜线,反斜线还可以取消变量替换,你如:
$res = "A quote \" and A backslash \\";
$result = 14;
print ("The value of \$result is $result.\n")的结果为:
The value of $result is 14.
可用\nnn(8进制)或\xnn(16进制)来表示ASCII字符,例如:
$result = "\377"; # this is the character 255,or EOF
$result = "\xff"; # this is also 255
单引号字符串与双引号字符串有两个区别,一是没有变量替换功能,二是反斜线不支持转义字符(\'除外).
单引号另一个特性是可以跨多行,例如:
$text = 'This is two
lines of text
';
与下句等效:
$text = "This is two\nlines of text\n";
在perl中除了双引号和单引号外,还支持其它的引用操作符,除了简单的引入字符串,还提供了许多功能.
详细如下表:
结构 结果(相当于) 是否插值 代表
q/str/ 'str' no 文字串
qq/str/ "str" yes 文字串
注:结构列中的/可以替换成你自定义的字符.
例:
my $test_str = q{I'm a word!};
my $test_str = qq[I'm a word!];
my $test_str = q/I'm a word!/;
my $test_str = qq#I'm a word!#;
注:不可以在引用内添加注释,例子中的第四行不是注释.
' " ', " \" ", ' \' ', " ' "等写法很难看,最好都改写成以上的这种直观的方式.
字符串和数值的互相转换,例如:
$string = "43";
$number = 28;
$result = $string + $number;
则$result = 71
若字符串中含有非数字的字符,则从左起至第一个非数字的字符,例如:
$result = "hello" * 5;
则$result = 0
$result = "12a34" +1;
则$result = 13
字符串常用的操作符是连接操作符"."和重复操作符"x".
例:
print "aaa"."bbb"."\n";
print "aaa"x3;
结果为:
aaabbb
aaaaaaaaa
4.undef变量
变量在第一次赋值前,会有一个特殊的值undef,意为"什么都没有".
undef值既非数字,又非字符串.它是另外一种标量变量.
undef值在需要数字的地方,它为0;在需要字符的地方,它为空串.
例如:
#n未定义
$a = $n + 3; #此时a等于3.
$b = $n."hello"; #此时b等于hello.
要分辨标量值是undef还是0或空串,可以使用defined函数,它将在变量为undef时返回false,其余的情况返回true.
#n未定义
print defined($n)."\n";
$n = "";
print defined($n)."\n";
如果要想自己定义一个undef变量,直接对其赋值undef即可.如:
$var = undef;
二.列表
列表是包含在括号里的一序列的值,可以为任何值,也可为空,例如:
(1, 5.3 , "hello" , 2),().
注:只含有一个数值的列表(如:(43.2) )与该数值本身(即:43.2 )是不同的,但它们可以互相转化或赋值.
列表例:
(17, $var, "a string")
(17, 26 << 2)
(17, $var1 + $var2)
($value, "The answer is $value")
如果列表内容都是字符串的话,可以采用qw简写的方式.
如:
("fred", "barney", "betty", "wilma", "dino")
简写形式如下
qw(fred barney betty wilma dino)
qw是一种引用,所以不可以里面添加注释,同时(可以换成自定义的字符,如qw#fred barney betty wilma dino#
列表范围:
(1..10) = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
(2, 5..7, 11) = (2, 5, 6, 7, 11)
(3..3) = (3)
用于实数
(2.1..5.3) = (2.1, 3.1 ,4.1, 5.1)
(4.5..1.6) = ()
用于字符串
("aaa".."aad") = ("aaa","aab", "aac", "aad")
@day_of_month = ("01".."31")
可包含变量或表达式
($var1..$var2+5)
小技巧:
$fred = "Fred";
print (("Hello, " . $fred . "!\n") x 2);
其结果为:
Hello, Fred!
Hello, Fred!
三.数组
数组是用来存储列表的变量,与简单变量不同,数组变量以字符"@"打头,例如:
@array = (1, 2, 3);
注:
(1)数组变量创建时初始值为空列表:().
(2)因为PERL用@和$来区分数组变量和简单变量,所以同一个名字可以同时用于数组变量和简单变量,例如:
$var = 1;
@var = (11, 27.1, "a string");
但这样很容易混淆,故不推荐.
1.数组的存取
对数组中的值通过下标存取,第一个元素下标为0.试图访问不存在的数组元素,则结果为undef,但如果给超出数组大小的元素赋值,则数组自动增长,原来没有的元素值为undef.例如:
@array = (1, 2, 3, 4);
$scalar = $array[0];
array[3] = 5;
现在@array的值为(1, 2, 3, 5)
$scalar = $array[4];
现在$scalar = null;
$array[6] = 17;
现在@array的值为(1,2,3,5,"","",17)
此外,$#代表数组的最后一个元素下标,可利用它来获取数组的最后一个元素.如:
@array = ('a', 1, 2, 'z', 'b');
print $array[$#array];
输出结果为b.
要获取数组的最后一个元素,也可以直接使用下标-1,如$array[-1],因为PERL中,负数下标值从最后一个开始.
数组间拷贝
@result = @original;
用数组给列表赋值
@list1 = (2, 3, 4);
@list2 = (1, @list1, 5);
则现在@list2 = (1, 2, 3, 4, 5)
数组对简单变量的赋值
@array = (5, 7, 11);
($var1, $var2) = @array;
此时$var1 = 5, $var2 = 7, 11被忽略
@array = (5, 7);
($var1, $var2, $var3) = @array;
此时$var1 = 5, $var2 = 7, $var3 =""(null)
从标准输入(STDIN)给变量赋值
$var = ;
@array = ;
# ^D为结束输入的符号
2.字符串中的方括号和变量替换
"$var[0]" 为数组@var的第一个元素.
"$var\[0]" 将字符"["转义,等价于"$var"."[0]",$var被变量替换,[0]保持不变.
"${var}[0]" 亦等价于"$var"."[0]".
"$\{var}"则取消了大括号的变量替换功能,包含文字:${var}.
3.数组的输出:
@array = (1, 2, 3);
print (@array, "\n");
结果为:
123
@array = (1, 2, 3);
print ("@array\n");
结果为:
1 2 3
4.列表/数组的长度
当数组变量出现在预期简单变量出现的地方,则PERL解释器取其长度.
@array = (1, 2, 3);
$scalar = @array;
此时$scalar = 3,即@array的长度
($scalar) = @array;
此时$scalar = 1,即@array第一个元素的值
注:以数组的长度为循环次数可如下编程:
$count = 1;
while ($count <= @array)
{
print ("element $count: $array[$count-1]\n");
$count++;
}
5.子数组
@array = (1, 2, 3, 4, 5);
@subarray = @array[0,1];
则@subarray = (1, 2)
@subarray2 = @array[1..3];
则@subarray2 = (2,3,4)
@array[0,1] = ("string", 46);
则现在@array = ("string",46,3,4,5)
@array[0..3] = (11, 22, 33, 44);
则现在@array = (11,22,33,44,5)
@array[1,2,3] = @array[3,2,4];
则现在@array = (11,44,33,5,5)
@array[0..2] = @array[3,4];
则现在@array = (5,5,"",5,5)
可以用子数组形式来交换元素:
@array[1,2] = @array[2,1];
6.有关数组的库函数
pop和push--读写数组
pop操作将数组的最后一个元素取出并返回.
@array = (123, 456, 789);
print pop(@array);
此时@array = (123, 456);
如果数组为空,那么pop什么都不做,返回undef.
push操作将一个元素添加到数组末尾.
@array = (123, 456);
push(@array, 789);
此时@array = (123, 456, 789);
shift和unshift--读写数组
这两个函数与pop和push相近,所不同的时,pop/push是在数组末尾操作,而shift/unshift是在数组头操作.
sort--按字符顺序排序
@array = ("this", "is", "a","test");
@array2 = sort(@array);
此时@array2 = ("a", "is", "test", "this")
@array = (70, 100, 8);
@array = sort(@array);
此时@array = (100, 70, 8)
reverse--反转数组
@array2 = reverse(@array);
@array2 = reverse sort (@array);
chop--数组去尾
chop的意义是去掉STDIN(键盘)输入字符串时最后一个字符--换行符.而如果它作用到数组上,则将数组中每一个元素都做如此处理.
@list = ("rabbit", "12345", "quartz");
chop (@list);
此时@list = ("rabbi", "1234","quart")
注:chop与chomp相近
chop()函数,只是去除最后一个字符.
chomp()函数,就要首先判断最后一个字符是不是为"\n",他才去除.
join/split--连接/拆分
join的第一个参数是连接所用的中间字符,其余则为待连接的字符数组.
$string = join(" ", "this", "is", "a", "string");
结果为"this is a string"
@list = ("words","and");
$string = join("::", @list, "colons");
结果为"words::and::colons"
@array = split(/::/,$string);
结果为@array = ("words", "and", "colons")
四.哈希表(关联数组)
Perl定义了另一种数组,可以用任意简单变量值来访问其元素,这种数组叫做关联数组,也叫哈希表.
为了区分关联数组变量与普通的数组变量,Perl使用%作为其首字符,而数组变量以@打头.
与其它变量名一样,%后的第一个字符必须为字母,后续字符可以为字母,数字或下划线.
1.访问关联数组的元素
关联数组的下标可以为任何简单变量(标量)值,访问单个元素时以$符号打头,下标用大括号围起来.
例如:
$fruit{"bananas"}
$number{3.14159}
$integer{-7}
简单变量也可作为下标.
$fruit{$my_fruit}
2.增加元素
创建一个关联数组元素最简单的方法是赋值.
例如:
$fruit{"bananas"} = 1;
把1赋给关联数组%fruit下标为bananas的元素,如果该元素不存在,则被创建.如果数组%fruit从未使用过,也被创建.
以下程序计算一个文件中,首字母大写的单词出现的次数:
1 #!/usr/bin/perl -w
2
3 $inputline = "";
4 while ($inputline = )
5 {
6 while ($inputline =~ /\b[A-Z]\S*\b/g)
7 {
8 $word = $&;
9 $counter{$word} += 1;
10 }
11 }
12 foreach $keyword (keys(%counter))
13 {
14 print $keyword.":".$counter{$keyword}."\n";
15 }
[root@server perl]# cat testfile
Here is a line of Input.
I love You.
This Input contains some Capitalized words.
[root@server perl]# ./testperl < testfile
I:1
You:1
Input:2
Here:1
This:1
Capitalized:1
本程序用关联数组%counter跟踪首字母大写的单词,下标就用单词本身,元素值为该单词出现的次数.第12行使用了内嵌函数keys(),这个函数返回关联数组的下标列表,foreach语句就用此列表循环.
注:关联数组总是随机存贮的,因此当你用keys()访问其所有元素时,不保证元素以任何顺序出现,特别值得一提的是,它们不会以被创建的顺序出现.
要想控制关联数组元素出现的次序,可以用sort()函数对keys()返回值进行排列.
如:
foreach $keyword (sort keys(%counter))
{
print $keyword.":".$counter{$keyword}."\n";
}
3.创建关联数组
可以用单个赋值语句创建关联数组.
如:
%fruit = ("apples",17,"bananas",9,"oranges","none");
此语句创建的关联数组含有下面三个元素:
* 下标为apples的元素,值为17
* 下标为bananas的元素,值为9
* 下标为oranges的元素,值为none
注:
用列表给关联数组赋值时,Perl5允许使用"=>"或","来分隔下标与值,用"=>"可读性更好些,上面语句等效于:
%fruit = ("apples"=>17,"bananas"=>9,"oranges"=>"none");
4.从数组变量复制到关联数组
与列表一样,也可以通过数组变量创建关联数组(当然,其元素数目应该为偶数).
如:
@fruit = ("apples",17,"bananas",9,"oranges","none");
%fruit = @fruit;
反之,可以把关联数组赋给数组变量
如:
%fruit = ("grapes",11,"lemons",27);
@fruit = %fruit;
注意:此语句中元素次序未定义,那么数组变量@fruit可能为("grapes",11,"lemons",27)或("lemons",27,"grapes",11).
关联数组变量之间可以直接赋值.
如:
%fruit2 = %fruit1;
还可以把数组变量同时赋给一些简单变量和一个关联数组变量.
如:
($var1, $var2, %myarray) = @list;
此语句把@list的第一个元素赋给$var1,第二个赋给$var2,其余的赋给%myarray.
最后,关联数组可以通过函数返回值来创建,当然函数的返回值必须为列表.
把split()函数的返回值赋给一个关联数组变量的例子:
1: #!/usr/local/bin/perl
2:
3: $inputline = ;
4: $inputline =~ s/^\s+|\s+\n$//g;
5: %fruit = split(/\s+/, $inputline);
6: print ("Number of bananas: $fruit{\"bananas\"}\n");
运行结果如下:
oranges 5 apples 7 bananas 11 cherries 6
Number of bananas: 11
5.元素的增删
增加元素已经讲过,可以通过给一个未出现过的元素赋值来向关联数组中增加新元素.
如:
$fruit{"lime"} = 1;
创建下标为lime、值为1的新元素.
删除元素的方法是用内嵌函数delete,如欲删除上述元素.
则:
delete ($fruit{"lime"});
注意:
1.一定要使用delete函数来删除关联数组的元素,这是唯一的方法.
2.一定不要对关联数组使用内嵌函数push、pop、shift及splice,因为其元素位置是随机的.
6.列出数组的索引和值
上面已经提到,keys()函数返回关联数组下标的列表.
如:
%fruit = ("apples", 9, "bananas", 23, "cherries", 11);
@fruitsubs = keys(%fruits);
这里,@fruitsubs被赋给apples、bananas、cherries构成的列表.
再次提请注意,此列表没有次序,若想按字母顺序排列,可使用sort()函数.
@fruitindexes = sort keys(%fruits);
这样结果为("apples","bananas","cherries").
类似的,内嵌函数values()返回关联数组值的列表.
如:
@fruitvalues = values(%fruits);
这里,@fruitvalues可能的结果为(9,23.11),次序可能不同.
7.用exists检验索引是否存在
要查看hash中是否存在某个key,可以使用exists函数,如果hash中存在此key,则返回true,这和是否有对应的value无关.
如:
my %fruit = ("apples"=>9, "bananas"=>23, "cherries"=>11);
if ( exists($fruit{"orange"}) )
{
print $fruit{"orange"}
}
该段代码将不会有任何输出,因为HASH中没有orange这个key.
8.用关联数组循环
前面已经出现过利用keys()函数的foreach循环语句,这种循环效率比较低,因为每返回一个下标,还得再去寻找其值.
如:
foreach $holder (keys(%records))
{
$record = $records{$holder};
}
Perl提供一种更有效的循环方式,使用内嵌函数each().
如:
%records = ("Maris", 61, "Aaron", 755, "Young", 511);
while (($holder, $record) = each(%records))
{
# stuff goes here
}
each()函数每次返回一个双元素的列表,其第一个元素为下标,第二个元素为相应的值,最后返回一个空列表.
注意:千万不要在each()循环中添加或删除元素,否则会产生不可预料的后果.
9.反转哈希表
我们可以将hash反转:
%inverse_hash = reverse %any_hash;
这会将%any_hash展开成key/value对的列表,其列表如(key,value,key,value,key,value,……).然后,将其反转,得到(value,key,value,key,value,key,……).value和key的位置交换了.
当将其存放在%inverse_hash,我们就可以查询对于%any_hash来说是value的字符串,因为现在它对于%inverse_hash来讲是key了,查询到的value对于%any_hash来讲属于key.
这给我们提供了一种方法:查询“value”(现在成了key),得到“key”(现在成了value).
五.引用
引用类似于C中的指针,用来指向数据项,而反引用则访问它所指向的实际数据.
PERL中有两种类型的引用:直接引用和符号引用.
直接引用就是按"地址"来引用数据项,可通过在变量前加\来获取地址.
例:
my @var = qw(one two three);
my $ref = \@var;
符号引用则不保存数据项的地址和类型,而是直接保存数据项的名称.
例:
$var = "hello";
$ref = "var";
1.读取引用所指的数据
要读取引用所指向的数据,需要使用前缀反引用符号.
例:
my @var = qw(one two three);
my $ref = \@var;
print @$ref[0]; #输出one
也可以使用箭头运算符.
my @var = qw(one two three);
my $ref = \@var;
print $ref->[0]; #输出one
2.匿名引用
PERL引用的强大之处在于可以直接存储对标量,数组,哈希和子程序的引用,而不是他们的名称.
例:
my $arrayref = [1, 2, 3]; #[]可够成匿名数组
printf $arrayref->[0]; #输出1
my $varref = \"Hello!";
print $$varref; #输出Hello!
my $hashref = { #{}可够成匿名哈希表
'a' => 'A',
'b' => 'B',
};
print $hashref->{a}; #输出A
3.把引用用在子程序中
例:
sub output
{
my ($a) = @_;
print $a->[2];
}
my @var = qw(one two three);
output( \@var ); #输出three
4.用ref函数确定引用类型
当新的子程序在处理引用时,如何知道当前正处理的是何种类型的引用?
用ref函数可以得到.ref函数可能会返回的值如下:
REF
SCALAR
ARRAY
HASH
CODE
GLOB
例:
my $varref = \"OK";
my $arrayref = [1, 2, 3];
print ref $varref; #输出SCALAR
print ref $arrayref; #输出ARRAY
阅读(5950) | 评论(0) | 转发(0) |