Perl学习笔记(2)-变量、数据

Perl的数据类型总览

Perl 是一种弱类型语言,所以变量不需要指定类型,Perl 解释器会根据上下文自动选择匹配类型。Perl 有三个基本的数据类型:标量、数组、哈希。

标量(scalar)

标量是Perl语言中最基本的一种数据类型。这种数据类型的变量可以是数字,字符串,浮点数,八进制等,不作严格的区分。在使用时在变量的名字前面加上一个$表示是标量。如下所示:

1
2
$myfirst=123;  #数字123 
$mysecond="123"; #字符串123

我不是太能理解标量的含义,我猜测可能是因为Perl擅长处理文本,而把一些最基本的符号,例如数字,字符串,浮点数都当作是一个东西,这样比较容易达到目的,毕竟Perl设计的初衷并不是为了处理一些数据。因此对于标量的理解,就把它当作是组成文本的最基本单位就行了。

define函数判断变量的定义

如果未定义变量,那么这个变量就会赋予undef的值,它不是数字,也不是字符串,有时候也会被当作数字0,使用defined函数会知道一个变量是否被定义了,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
biotest@ubuntu:~/perl/01basic$ cat define.pl
#!/usr/bin/perl -w
$var = undef;
print ($var);
if (defined($var)){
print("definded!\n");
}else{
print("undefined!\n");
}
$var++;
print($var."\n");
biotest@ubuntu:~/perl/01basic$ perl define.pl
Use of uninitialized value $var in print at define.pl line 4.
undefined!
1

单引号内的字符串

单引号内的字符串直接量指的是一对单引号内的一串字符,这两个单引号并不属于字符串的内容。如果要表示单引号,需要加反斜线进行转义,如下所示:

1
2
3
'fred' # 共4个字符,即f、r、e、d
'' # 空字符
'Dont\'t' # 加了反斜线进行转义

双引号内的字符串

双引号可以转义许多字符,或者是用八进制或十六进制写法来表示任何字符,如下所示:

1
2
3
"barney" # 这种写法与'barney'写法一样
"hello world\n" # 输出为helloworld,后面接着换行符
"coke\tspirte" # 输出结果为coke、制表符、spirte

Perl中的转义字符

转义字符 含义
\\ 反斜线
\’ 单引号
\” 双引号
\a 系统响铃
\b 退格
\f 换页符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\0nn 创建八进制格式的数字
\xnn 创建十六进制格式的数字
\cX 控制字符,x可以是任何字符
\u 强制下一个字符为大写
\l 强制下一个字符为小写
\U 强制将所有字符转换为大写
\L 强制将所有的字符转换为小写
\Q 将到\E为止的非单词(non-word)字符加上反斜线
\E 结束\L、\U、\Q

转义字符的使用案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
biotest@ubuntu:~/perl/02datatype$ cat escapecharacter.pl
#!/usr/bin/perl
$result = "newbie tutorial \"runoob\"";
print "$result\n";
print "\$result\n";
$str="BAIDU search \nwwww.baidu.com";
print "$str\n";
$str='BAIDU search \nwwww.baidu.com';
print "$str\n";
$str = '\Ulinux';# 单引号不能进行转义
print "$str\n";
$str = "Welcome to \Utaobao\E.com!"; # 大写E表示大写到此终止
print "$str\n";
# Notice following code don't contain E
$str="Welcome to \Utaobao.com";
print "$str\n";
biotest@ubuntu:~/perl/02datatype$ perl escapecharacter.pl
newbie tutorial "runoob"
$result
BAIDU search
wwww.baidu.com
BAIDU search \nwwww.baidu.com
\Ulinux
Welcome to TAOBAO.com!
Welcome to TAOBAO.COM

字符串操作

字符串的连接使用点号(.),如下所示:

1
2
3
4
5
6
7
8
biotest@ubuntu:~/perl/01basic$ cat dot.pl
#!/usr/bin/perl
$hello="hello";
$world="world";
print $hello.$world."\n";
biotest@ubuntu:~/perl/01basic$ perl dot.pl
helloworld
biotest@ubuntu:~/perl/01basic$

字符串也能做乘法,如下所示:

1
2
3
#!/usr/bin/perl
$word="fred";
print $word x 3; # 这个格式是变量+空格+小写字母x+空格+数字

运行结果如下所示:

1
2
biotest@ubuntu:~/perl/02datatype$ perl repeat.pl
fredfredfredbiotest@ubuntu:~/perl/02datatype$

数字与字符串之间的自动转换

通常Perl会根据需要,自动在数字和字符串之间进行类型转换。这主要取决于操作符,如果操作符(比如+)需要的是数字,Perl就会将操作数视为数字,如果是操作符(比如点号)需要字符串时,Perl便会将操作数视为字符串。因此,你不必担心数字和字符串间的差异,只管合理使用操作符,Perl会自动完成剩下的工作。

对数字进行运算的操作符(例如乘法),如果遇到字符串类型的操作,Perl会自动将字符串转换成等效的十进制浮点数进行运算,例如"12"*"3"的结果会是36,字符串中非数字的部分(以前前置的空白符号)会被忽略,因此,”12fred34”*”3”也会得到36。完全不含数字的字符串会被转换为零。“前置零”只对直接量有效,不能用于字符串的自动转换,自动转换只能按照十进制数字来处理,例如:

1
2
0377 # 十进制数字255的八进制写法
'0377' # 会转换成十进制数字377,任何其他进制的数字都会被转换为十进制

在进行字符串的操作时(例如使用字符串连接符号)意外得到数字时,为数字就会被转换为形式相的字符串。比如要把字符串Z与“5乘以7的结果”相连接,就如下所示:

1
"Z". 5*7 #等同于"Z".35,得到"Z35"

标量变量

Perl中变量是通过前面的符号来区分的,这个符号称为魔符(sigil),变量分为标量变量(用$来区分),数组变量(用@来区分),哈希变量(用%来区分)。

标量变量的赋值

变量不需要声明类型,在变量赋值后,解释器会自动分配匹配的类型空间,变量使用等号(=)来赋值,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
biotest@ubuntu:~/perl/02datatype$ cat variable.pl
#!/usr/bin/perl
$age=25; # 整型
$name="Zhang San"; # 字符串
$number=123.456;# 浮点数
print "Age=$age\n";
print "Name=$name\n";
print "Salary=$number\n";
biotest@ubuntu:~/perl/02datatype$ perl variable.pl
Age=25
Name=Zhang San
Salary=123.456

借助代码点创建字符

用于编码抽象字符的整数范围叫做代码空间,其中的特殊整数叫做代码点(code point),简单来说,就是处理一些不常见字符的代码。在Perl中,使用代码点,然后使用chr()函数转换为对应的字符,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~/perl/02datatype$ cat codepoint.pl
#!/usr/bin/perl
$alef=chr(0x05D);
$alpha=chr(hex('03B1'));
$omega=chr(0x03C9);
print "This is $alef\n";
print "This is alpha, $alpha\n";
print "This is omega, $omega\n";
biotest@ubuntu:~/perl/02datatype$ perl codepoint.pl
This is ]
Wide character in print at codepoint.pl line 6.
This is alpha, α
Wide character in print at codepoint.pl line 7.
This is omega, ω

从结果可以看出,使用代码点可以输出一些特殊字符,结果中还有一些提示信息,提示这些字符是宽字符,先不用管它们。

数组

如果把Perl的标量(scalar)理解为单数(singular),那么Perl里的复数(plural)就是数组与列表。数组是用于存储一个有序的标量值的变量。数组用@表示,要访问数组的变量,可以使用美元符号($)+变量名,并指定下标来访问,实例如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
biotest@ubuntu:~/perl/02datatype$ cat array.pl
#!/usr/bin/perl
@ages=(25,30,40);
@names=("google","runoob","taobao");
print"\$ages[0]=$ages[0]\n";
# 在 $ 标记前使用了转义字符 (\) ,这样才能输出字符 $
print"\ages[1]=$ages[1]\n";
print"\$ages[2]=$ages[2]\n";
print"\ages[0]=$ages[0]\n";
print"\$ages[1]=$ages[1]\n";
print"\$ages[2]=$ages[2]\n";
print"\$ages[-1]=$ages[-1]\n";
# 在Perl中,可以使用-1表示最后一个索引
biotest@ubuntu:~/perl/02datatype$ perl array.pl
$ages[0]=25
ges[1]=30
$ages[2]=40
ges[0]=25
$ages[1]=30
$ages[2]=40
$ages[-1]=40

列表

列表是包含在括号里的一序列的值,可以为任何数值,也可为空,如(1, 5.3 , "hello" , 2),空列表:(),下面都是列表:

1
2
3
4
(17, $var, "a string")
(17, 26 << 2)
(17, $var1 + $var2)
($value, "The answer is $value")

列表存贮于数组变量中,数组变量以字符”@”打头,以@ages=(25,30,40);为例说明一下:

mark

数组还可以产使用qw定义数组,如下所示:

1
2
3
4
5
6
7
8
9
10
biotest@ubuntu:~/perl/02datatype$ cat qw.pl
#!/usr/bin/perl
@array1=(1,2,'hello');
@array2=qw/this is an array/;
print("@array1\n");
print("@array2\n");
biotest@ubuntu:~/perl/02datatype$ perl qw.pl
1 2 hello
this is an array

Perl提供了可以按序列输出的数组形式,格式为起始值 + .. + 结束值,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~/perl/02datatype$ cat dot2.pl
#!/usr/bin/perl
@var_10=(1..10);
@var_20=(10..20);
@var_abc=(a..z);
print "@var_10\n";
print "@var_20\n";
print "@var_abc\n";
biotest@ubuntu:~/perl/02datatype$ perl dot2.pl
1 2 3 4 5 6 7 8 9 10
10 11 12 13 14 15 16 17 18 19 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

数组长度返回的是数组物理大小,而不是元素的个数,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/02datatype$ cat size.pl
#!/usr/bin/perl
@array=(1,2,3);
$array[50]=4;
$size=@array;
$max_index=$#array;
print "the size of array: $size\n";
print "the max of index: $max_index\n";
biotest@ubuntu:~/perl/02datatype$ perl size.pl
the size of array: 51
the max of index: 50

从输出的结果可以看出,数组元素只有四个,但是数组大小为 51。

添加与删除数组元素

添加和删除数组元素,数组中常用的操作函数如下所示:

  1. push @ARRAY, LIST——将列表的值放到数组的末尾
  2. pop @ARRAY——弹出数组最后一个值,并返回它
  3. shift @ARRAY——弹出数组第一个值,并返回它。数组的索引值也依次减一。
  4. unshift @ARRAY, LIST——将列表放在数组前面,并返回新数组的元素个数。

看下面的案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
biotest@ubuntu:~/perl/02datatype$ cat array_del.pl
#!/usr/bin/perl
# creat a simple array
@sites=("google","microsoft","ibm");
print"1.\@sites=@sites\n";
# add an element in the end of the array:
push(@sites,"intel");
print"2.\@sites=@sites\n";
# add an element in the beginning of the array:
unshift(@sites,"sun");
print"3.\@sites=@sites\n";
# delete an element in the end of the array:
pop(@sites);
print"4.\@sites=@sites\n";
# delete an element in the begining of the array:
shift(@sites);
print"5.\@sites=@sites\n";
biotest@ubuntu:~/perl/02datatype$ perl array_del.pl
1.@sites=google microsoft ibm
2.@sites=google microsoft ibm intel
3.@sites=sun google microsoft ibm intel
4.@sites=sun google microsoft ibm
5.@sites=google microsoft ibm

切割数组

切割一个数组,并返回切割后的新数组,如下所示:

1
2
3
4
5
6
7
8
biotest@ubuntu:~/perl/02datatype$ cat cut.pl
#!/usr/bin/perl
@sites=qw/google tencent jd facebook 163 microsoft/;
@sites2=@sites[3,4,5];
print "@sites2\n";
biotest@ubuntu:~/perl/02datatype$ perl cut.pl
facebook 163 microsoft

替换数组元素

Perl 中数组元素替换使用 splice() 函数,语法格式如下:

1
splice @ARRAY, OFFSET [ , LENGTH [ , LIST ] ]

参数说明:

  1. @ARRAY:要替换的数组。
  2. OFFSET:起始位置。
  3. LENGTH:替换的元素个数。
  4. LIST:替换元素列表。

以下案例从第6个元素开始替换数组中的5个元素:

1
2
3
4
5
6
7
8
9
10
biotest@ubuntu:~/perl/02datatype$ cat replace.pl
#!/usr/bin/perl
@nums=(1..20);
print "Before replacement--@nums\n";
splice(@nums,5,6,20..25);
print "After replacement--@nums\n";
biotest@ubuntu:~/perl/02datatype$ perl replace.pl
Before replacement--1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
After replacement--1 2 3 4 5 20 21 22 23 24 25 12 13 14 15 16 17 18 19 20

可以看出来,从第6个元素开始替换,替换的是从第5个元素开始往后的6个元素。

将字符串转换为数组

Perl 中将字符串转换为数组使用 split() 函数,语法格式如下:

1
split [ PATTERN [ , EXPR [ , LIMIT ] ] ]

参数说明:

  1. PATTERN:分隔符,默认为空格。
  2. EXPR:指定字符串数。
  3. LIMIT:如果指定该参数,则返回该数组的元素个数。

看下面的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
biotest@ubuntu:~/perl/02datatype$ cat trans_character_array.pl
#!/usr/bin/perl
# define string:
$var_test="baidu";
$var_string="www-baidu-com";
$var_names="google, interl, baidu,ati";
# transform strings into array:
@test=split('',$var_test);
@string=split('-',$var_string);
@names=split(',',$var_names);
print "$test[3]\n"; # output character "d"
print "$string[2]\n"; # output character "com"
print "$names[3]\n"; # output character "ati"
biotest@ubuntu:~/perl/02datatype$ perl trans_character_array.pl
d
com
ati

将数组转换为字符串

Perl 中将数组转换为字符串使用 join() 函数,语法格式如下:

1
join EXPR, LIST

参数说明:

  1. EXPR:连接符。
  2. LIST:列表或数组。

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
biotest@ubuntu:~/perl/02datatype$ cat array_into_string.pl
#!/usr/bin/perl
# defing string:
$var_string="wwww-baidu-com";
$var_names="google,intel,ibm,tencent";
# Transform string into array:
@string=split('-',$var_string);
@names=split(',',$var_names);
# Transform array into string:
$string1=join('-',@string);
$string2=join(',',@names);
print "$string1\n";
print "$string2\n";
biotest@ubuntu:~/perl/02datatype$ perl array_into_string.pl
wwww-baidu-com
google,intel,ibm,tencent

数组排序

Perl 中数组排序使用 sort() 函数,语法格式如下:

1
sort [ SUBROUTINE ] LIST

参数说明:

  1. SUBROUTINE:指定规则。
  2. LIMIT:列表或数组。

案例如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/02datatype$ cat sort.pl
#!/usr/bin/perl
@sites=qw(ibm tencent amzon sun microsoft interl);
print "beofore sorting: @sites\n";
# sort array
@sites=sort(@sites);
print "After sorting: @sites\n";
biotest@ubuntu:~/perl/02datatype$ perl sort.pl
beofore sorting: ibm tencent amzon sun microsoft interl
After sorting: amzon ibm interl microsoft sun tencent

合并数组

数组的元素是以逗号来分割,我们也可以使用逗号来合并数组,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
biotest@ubuntu:~/perl/02datatype$ cat merge.pl
#!/usr/bin/perl
@n1=(1,2,3);
@n2=(3,4,5);
@n =(@n1,@n2);
print "numbers1:@n1\n";
print "numbers2:@n2\n";
print "Merge numbers1 and numbers2:@n\n";
biotest@ubuntu:~/perl/02datatype$ perl merge.pl
numbers1:1 2 3
numbers2:3 4 5
Merge numbers1 and numbers2:1 2 3 3 4 5

从列表中选择元素

一个列表可以当作一个数组使用,在列表后指定索引值可以读取指定的元素,如下所示:

1
2
3
4
5
6
biotest@ubuntu:~/perl/02datatype$ cat select.pl
#!/usr/bin/perl
$var = (11, 22, 44, 444, 5555)[4];
print "the value of var is: $var\n";
biotest@ubuntu:~/perl/02datatype$ perl select.pl
the value of var is: 5555

同样可以在数组中使用 .. 来读取指定范围的元素:

1
2
3
4
5
6
7
biotest@ubuntu:~/perl/02datatype$ cat range_array.pl
#!/usr/bin/perl
@list = (5, 4, 3, 2, 1)[1..3];
print "list的值 = @list\n";
biotest@ubuntu:~/perl/02datatype$ perl range_array.pl
list的值 = 4 3 2

哈希

哈希是一个key/value对的集合,可以把它理解为Python中的字典。哈希%开始。如果要访问哈希值,可以使用$+{key}格式来访问,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~/perl/02datatype$ cat hash.pl
#!/usr/bin/perl
%data=('google',45,'runoob',30,'taobao',40);
print "\$data{'google'} = $data{'google'}\n";
print "\$data{'runoob'} = $data{'runoob'}\n";
print "\$data{'taobao'} = $data{'taobao'}\n";
biotest@ubuntu:~/perl/02datatype$ perl hash.pl
$data{'google'} = 45
$data{'runoob'} = 30
$data{'taobao'} = 40

创建哈希

创建哈希有两种方式:第一,为每个key设置value;第二,通过列表创建。
先看第一种方式,如下所示:

1
2
3
$site{'google'}='google.com';
$site{'bing'}='bing.com';
$site{'baidu'}='baidu.com';

第二种,通过列表设置,如下所示:

1
%data=('google','google.com','bing','bing.com','taobao','taobao.com')

也可以使用=>符号来设置key/value,如下所示:

1
%data=('google'=>'google.com','bing'=>'bing.com','taobao'=>'taobao.com')

也可以使用-来代替引号,如下所示:

1
%data=(-google=>'google.com',-bing=>'bing.com',-taobao=>'taobao.com')

不过这种方式创建的哈希,需要key不能出现空格,读取元素方式为:

1
2
$val = $data{-google}
$val = $data{-runoob}

访问哈希

访问哈希元素格式:${key},如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/02datatype$ cat access_hash.pl
#!/usr/bin/perl
%data=('google'=>'google.com','baidu'=>'baidu.com','mit'=>'mit.edu');
print "\$data{'google'}=$data{'google'}\n";
print "\$data{'baidu'}=$data{'baidu'}\n";
print "\$data{'mit'}=$data{'mit'}\n";
biotest@ubuntu:~/perl/02datatype$ perl access_hash.pl
$data{'google'}=google.com
$data{'baidu'}=baidu.com
$data{'mit'}=mit.edu

读取哈希的keyvalue

读取hash的key

我们可以使用keys函数读取哈希所有的键,语法格式如下:

1
keys %HASH

该函数返回所有哈希的所有 key 的数组,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~/perl/02datatype$ cat values_hash.pl
#!/usr/bin/perl
%data=('google'=>'google.com','abc'=>'abc.com','UFO'=>'ufo.com');
@names=keys %data;
print "$names[0]\n";
print "$names[1]\n";
print "$names[2]\n";
biotest@ubuntu:~/perl/02datatype$ perl values_hash.pl
UFO
google
abc

读取hash的value

使用values函数读取hash的值,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~/perl/02datatype$ cat value_hash.pl
#!/usr/bin/perl
%data=('google'=>'google.com','abc'=>'abc.com','UFO'=>'ufo.com');
@url=values%data;
print "$url[0]\n";
print "$url[1]\n";
print "$url[2]\n";
biotest@ubuntu:~/perl/02datatype$ perl value_hash.pl
google.com
abc.com
ufo.com

检测元素是否存在

如果你在哈希中读取不存在的key/value对 ,会返回undefined值,且在执行时会有警告提醒。为了避免这种情况,我们可以使用exists函数来判断key是否存在,存在的时候读取,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
biotest@ubuntu:~/perl/02datatype$ cat exists.pl
#!/usr/bin/perl
%data=('google'=>'google.com','sina'=>'sina.com','taobao'=>'taobao.com');
if (exists($data{'facebook'})){
print "the website of factbook is $data{'facebook'}\n";
}
else
{
print "facebook doesn't exist\n";
}
biotest@ubuntu:~/perl/02datatype$ perl exists.pl
facebook doesn't exist

获取哈希大小

哈希大小为元素的个数,我们可以通过先获取keyvalue的所有元素数组,再计算数组元素多少来获取哈希的大小,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
biotest@ubuntu:~/perl/02datatype$ cat size_of_hash.pl
#!/usr/bin/perl
%data=('google'=>'google.com','sina'=>'sina.com','taobao'=>'taobao.com');
@keys=keys%data;
$size=@keys;
print "1- size of hash: $size\n";
@values=values%data;
$size=@values;
print "2- size of hash: $size\n";
biotest@ubuntu:~/perl/02datatype$ perl size_of_hash.pl
1- size of hash: 3
2- size of hash: 3

哈希中添加或删除元素

delete函数用于删除哈希中的元素;使用赋值来添加哈希中的元素,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
biotest@ubuntu:~$ cat delete.pl
#!/usr/bin/perl
%data=('google'=>'google.com','baidu'=>'baidu.com','bing'=>'bing.com');
@keys=keys%data;
$size=@keys;
print "1-The size of hash: $size\n";
# add element:
$data{'facebook'}='facebook.com';
@keys=keys%data;
$size=@keys;
print "2-The size of hash:$size\n";
# delete element:
delete $data{'baidu'};
@keys=keys%data;
$size=@keys;
print "3-The size of hash: $size\n";
biotest@ubuntu:~$ perl delete.pl
1-The size of hash: 3
2-The size of hash:4
3-The size of hash: 3

变量上下文

所谓上下文:指的是表达式所在的位置。上下文是由等号左边的变量类型决定的,等号左边是标量,则是标量上下文,等号左边是列表,则是列表上下文。Perl解释器会根据上下文来决定变量的类型,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/02datatype$ cat context.pl
#!/usr/bin/perl
@names = ('google','baidu','sogou');
@copy = @names;
$size=@names;
print "Names is: @copy\n";
print "Name is :$size\n";
biotest@ubuntu:~/perl/02datatype$ perl context.pl
Names is: google baidu sogou
Name is :3

代码及结果解释:代码中@names是一个数组,它应用在了两个不同的上下文中。第一个将其复制给另外一个数组@copy,所以它输出了数组的所有元素。第二个我们将数组赋值给一个标量,它返回了数组的元素个数。以下列出了多种不同的上下文:

序号 上下文及描述
1 标量 −赋值给一个标量变量,在标量上下文的右侧计算
2 列表 −赋值给一个数组或哈希,在列表上下文的右侧计算。
3 布尔 −布尔上下文是一个简单的表达式计算,查看是否为 true 或 false。
4 Void −这种上下文不需要关系返回什么值,一般不需要返回值。
5 插值 −这种上下文只发生在引号内。

Perl的内置警告信息

从Perl 5.6开始,就能心通过编译指令开启警告功能,如下所示:

1
2
#!/usr/bin/perl
usr warnings;

也可以在命令行上使用-w选项开启警告,如下所示:

1
perl -w my_program

例如,如果用户把12fred34当成数字用,Perl就会发出警告,如下所示:

1
ARgument "12fred34" isn't numeric

全局特殊常量

在Perl中有一些特殊的字符的应用例如.__FILE__., .__LINE__..__PACKAGE__.(注意,这是一个点加两条下划线),它们分别表示当前执行脚本的文件名,行号,包名,这些特殊字符是单独的标记,不能写在字符串中,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~$ cat special_string.pl
#!/usr/bin/perl
print "The name of script file " .__FILE__."\n";
print "The line number of scripte file ".__LINE__."\n";
print "The name of package ".__PACKAGE__."\n";
# Following code will not run:
print ".__FILE__. .__LINE__. .__PACKAGE__. \n";
biotest@ubuntu:~$ perl special_string.pl
The name of script file special_string.pl
The line number of scripte file 4
The name of package main
.__FILE__. .__LINE__. .__PACKAGE__.
变量 描述
__END__ 脚本的逻辑结束,忽略后面的文本。
__FILE__ 当前文件名
__LINE__ 当前行号
__PACKAGE__ 当前包名,默认的包名是main。

Perl特殊变量

Perl语言中定义了一些特殊的变量,通常以$@,或%作为前缀,例如$_。很多特殊的变量有一个很长的英文名,操作系统变量$!可以写为$OS_ERROR。如果你想使用英文名的特殊变量需要在程序头部添加use English;。这样就可以使用具有描述性的英文特殊变量。最常用的特殊变量为$_,该变量包含了默认输入和模式匹配内容。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/02datatype$ cat special_variable.pl
#!/usr/bin/perl
foreach('Google','Baidu','Tencent'){
print $_;
print "\n";
}
biotest@ubuntu:~/perl/02datatype$ perl special_variable.pl
Google
Baidu
Tencent

如果不使用$_作为输出,则是这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/02datatype$ cat output.pl
#!/usr/bin/perl
foreach('Google','Baidu','Tencent'){
print;
print"\n";
}
biotest@ubuntu:~/perl/02datatype$ perl output.pl
Google
Baidu
Tencent

实例中,首先输出”Google”,接着输出”Baidu”,最后输出”Tencent”。在迭代循环中,当前循环的字符串会放在$_中,然后通过print输出。另外print在不指定输出变量,默认情况下使用的也是$_

以下是几处即使没有写明Perl也会假定使用$_的地方:

  1. 各种单目函数,包括像ord()int()这样的函数以及除"-t"以外所有的文件测试操作("-f","-d")"-t"默认操作STDIN
  2. 各种列表函数,例如print()unlink()
  3. 没有使用"=~"运算符时的模式匹配操作"m//""s///""tr///"
    4 在没有给出其他变量时是"foreach"循环的默认迭代变量。
  4. grep()map()函数的隐含迭代变量。
  5. "while"仅有唯一条件,且该条件是对””操作的结果进行测试时,$_就是存放输入记录的默认位置。除了"while"测试条件之外不会发生这种情况。(助记:下划线在特定操作中是可以省略的。)

特殊变量类型

根据特殊的变量的使用性质,可以分为以下几类:

  1. 全局标量特殊变量。
  2. 全局数组特殊变量。
  3. 全局哈希特殊变量。
  4. 全局特殊文件句柄。
  5. 全局特殊常量。
  6. 正则表达式特殊变量。
  7. 文件句柄特殊变量。

全局标量特殊变量

以下列出了所有的标量特殊变量,包含了特殊字符与英文形式的变量:

特殊字符 对应的英文形式变量 描述
$_ $ARG 默认输入和模式匹配内容。
$. $NR 前一次读的文件句柄的当前行号
$/ $RS 输入记录分隔符,默认是新行字符。如用undef这个变量,将读到文件结尾。
$, $OFS 输出域分隔符
$\ $ORS 输出记录分隔符
$" $LIST_SEPARATOR 该变量同 $,类似,但应用于向双引号引起的字符串(或类似的内插字符串)中内插数组和切片值的场合。默认为一个空格。
$; $SUBSCRIPT_SEPARATOR 在仿真多维数组时使用的分隔符。默认为 "\034"
$^L $FORMAT_FORMFEED 发送到输出通道的走纸换页符。默认为 "\f".
$: $FORMAT_LINE_BREAK_CHARACTERS The current set of characters after which a string may be broken to fill continuation fields (starting with ^) in a format. Default is "\n"".
$^A $ACCUMULATOR 打印前用于保存格式化数据的变量
$# $OFMT 打印数字时默认的数字输出格式(已废弃)。
$? $CHILD_ERROR 返回上一个外部命令的状态
$! $OS_ERROR or $ERRNO 这个变量的数字值是errno的值,字符串值是对应的系统错误字符串
$@ $EVAL_ERROR 命令eval的错误消息.如果为空,则表示上一次eval命令执行成功
$$$$ $PROCESS_ID or $PID 运行当前Perl脚本程序的进程号
$< $REAL_USER_ID or $UID 当前进程的实际用户号
$> $EFFECTIVE_USER_ID or $EUID 当前进程的有效用户号
$( $REAL_GROUP_ID or $GID 当前进程的实际组用户号
$) $EFFECTIVE_GROUP_ID or $EGID 当前进程的有效组用户号
0 $PROGRAM_NAME 包含正在执行的脚本的文件名
$[ 数组的数组第一个元素的下标,默认是 0。
$] $PERL_VERSION Perl的版本号
$^D $DEBUGGING 调试标志的值
$^E $EXTENDED_OS_ERROR 在非UNIX环境中的操作系统扩展错误信息
$^F $SYSTEM_FD_MAX 最大的文件捆述符数值
$^H 由编译器激活的语法检查状态
$^I $INPLACE_EDIT 内置控制编辑器的值
$^M 备用内存池的大小
$^O $OSNAME 操作系统名
$^P $PERLDB 指定当前调试值的内部变量
$^T $BASETIME 从新世纪开始算起,脚步本以秒计算的开始运行的时间
$^W $WARNING 警告开关的当前值
$^X $EXECUTABLE_NAME Perl二进制可执行代码的名字
$ARGV 从默认的文件句柄中读取时的当前文件名

全局数组特殊变量

变量 描述
@ARGV 传给脚本的命令行参数列表
@INC 在导入模块时需要搜索的目录列表
@F 命令行的数组输入

全局哈希特殊变量

变量 描述
%INC 散列表%INC包含所有用do或require语句包含的文件.关键字是文件名,值是这个文件的路径
%ENV 包含当前环境变量
%SIG 信号列表及其处理方式

全局特殊文件句柄

变量 描述
ARGV 遍历数组变量@ARGV中的所有文件名的特殊文件句柄
STDERR 标准错误输出句柄
STDIN 标准输入句柄
STDOUT 标准输出句柄
DATA 特殊文件句柄引用了在文件中 __END__ 标志后的任何内容包含脚本内容。或者引用一个包含文件中__DATA__标志后的所有内容,只要你在同一个包有读取数据,__DATA__就存在。
_ (下划线) 特殊的文件句柄用于缓存文件信息(fstat、stat和lstat)。

正则表达式特殊变量

变量 英文形式变量 描述
$n 包含上次模式匹配的第n个子串
$& $MATCH 前一次成功模式匹配的字符串
$` $PREMATCH 前次匹配成功的子串之前的内容
$' $POSTMATCH 前次匹配成功的子串之后的内容
$+ $LAST_PAREN_MATCH 与上个正则表达式搜索格式匹配的最后一个括号。例如:`/Version: (.*) Revision: (.*)/ && ($rev = $+);`

文件句柄特殊变量

变量 英文形式变量 描述
`$ ` $OUTPUT_AUTOFLUSH 如果设置为零,在每次调用函数write或print后,自动调用函数fflush,将所写内容写回文件
$% $FORMAT_PAGE_NUMBER 当前输出页号
$= $FORMAT_LINES_PER_PAGE 当前每页长度。默认为 60。
$- $FORMAT_LINES_LEFT 当前页剩余的行数
$~ $FORMAT_NAME 当前报表输出格式的名称。默认值是文件句柄名。
$^ $FORMAT_TOP_NAME 当前报表输出表头格式的名称。默认值是带后缀”_TOP”的文件句柄名。

参考资料

Perl教程|菜鸟教程