title: Perl语言入门(一) date: 2015-08-10 14:55:36 tags: [学习笔记]

更新记录:

  • 2015/08/10 DonePage45
  • 2015/08/11 DonePage68
  • 2015/08/17 Read list and array, do a new one.

##前言杂记

  • 适合管理员使用的语言
  • Arvon’s读书笔记
  • sixth edtion for learning perl
1
2
use 5.014;#该脚本需要在Perl 5.14或更高版本才能正常运行
perl -v#查看perl的版本
  • Hello,World
1
2
3
4
#!/usr/bin/perl
printf "Hello, world!\n";
use 5.010;
say "Hello, world!";
  • 替换字符演示
1
2
3
4
5
6
#!/usr/bin/perl
@lines = `perldoc -u -fatan2`;
foreach (@lines){
    s/\w<([^>]+)>/\U$1/g;
        print;
        }

##标量数据

  • 标量数据是Perl里面最简单的一种数据类型。对大部分标量来说,它要么是数字(如123或3.25e23),要 么是由字符组成的序列(如hello)。对Perl来说,数字和字符串大多情况下是可以在内部转换的。可以用操 作符对标量进行操作(如加法或字符串连接),产生的结果通常也是一个标量。标量可以存储在标量变量里, 也可以从文件和设备读取或写入这些位置。

###数字 ####所有数字的内部格式都相同

  • Perl内部,总是按“双精度浮点数(double-precision floating-point)”的要求来保存数字并进行运算 的。也就是说,Perl内部并不存在整数值–程序中用到的整数型常量会被转换成等效的浮点数值。

####浮点数直接量

  • 直接量(literal)是指某个数字在Perl源代码中的写法。直接量并非运算结果,也不是I/O(输入/输出) 操作的结果,它只是直接键入源程序代码中的数据。
  • Perl浮点数直接量的写法,小数点与前置的正负号都是可选的,数字后面也可以加上用“e”表示的10的次方 表示符(即指数表示法)。
  • 如下列写法

1.25 255.000 255.0 7.25e45 #7.25乘以10的45次方,其中e可以大写 -6.5e123

####整数直接量

  • 整数直接量:

0 1234 -4321 41023789873 #可以写成41_023_789_873,Perl允许在整数直接量插入下划线,方便辨认

####非十进制的整数直接量

  • Perl语言和其他许多程序语言一样,允许使用十进制(decimal)意外的其他进制表示数字。八进制(octal) 直接量以0开头,十六进制(hexadecimal)直接量以ox开头,二进制(binary)直接量以ob开头。十六进制的 A到F(可以写成小写的a到f,来代表十进制的10到15)。例如

o377 #八进制的377,等于十进制的255 0xff #十六进制的FF,等于十进制的255 ob11111111 #二进制的,等于十进制的255

  • 这三个数字虽然看起来不同,但对Perl来说都是同一个数字

####数字操作符

  • Perl提供了各种常见的数字操作符,如加、减、乘、除、取模、次方。例如:

2+3 5.1-2.4 3*12 14/2 10.2/0.3 10/3 10%3 #取模,结果为1 2**3 #次方,结果为8

###字符串

  • 字符串就是一个字符序列,如hello。字符串可以各种字符任意组合而成。最短的字符串不包含任何字符,也 叫做空字符串。最长的字符串的长度没有限制。这符合Perl遵守的“无内置限制(nobuilt-inlimits)”的原则。 字符串通常是由可输出地字母、数字及标点符号组成,其范围介于ASCII编码的32到126之间。由于字符串可以 包含任何字符,所以可用它来创建、扫描或操控二进制数据,这是许多其他工具语言望尘莫及的。例如:你可以 将一个图形文件或编译过的可执行文件读进Perl的字符串变变量,修改它的内容再写回去。
  • Perl完全支持Unicode,所以在字符串中可以使用任意一个合法的Unicode字符。不过由于Perl的历史原因 它不会自动将程序源代码当做Unicode编码的文本读入,所以如果你想要在源代码中使用Unicode书写直接量 的话,需手工加上utf8编译指令:
1
use utf8;
  • 和数字一样,字符串也有直接量记法,也就是Perl程序中字符串的书写方式。包括单引号内的字符串和双引号 内的字符串。

####单引号内的字符串直接量

  • 除了单引号和反斜线之外,单引号内所有的字符串都代表他们自己。

‘fred’ ‘hello’ '' ‘#$@%’ ‘Don't let me go!’ ‘the last character is a backslash:\’ ‘'\’ #单引号后面紧接着反斜线 ‘hi\n’ #单引号内的\n并不是换行符,而是表示字面上的两个字符

####双引号内的字符串直接量

  • 双引号中的反斜线更为强大

“hi\n” #换行符 “love\tyou” #水平制表符 “\r” #回车 “\f” #换页符 “\b” #退格 “\e” #Esc(ASCII编码的转义字符) “\cC” #控制符,就是COntrol键的代码(此例表示同时按下Ctrl和c键的返回码) “\l” #将下个字母转换为小写 “\L” #将它后面的所有字母都转换为小写的,直到\E为止 “\u” #将下个字符转换为大写 “\U” #将它后面所有的字母都转换为大写,直到\E为止 “\E” #结束\L、\U和\Q开始的作用范围

####字符串操作符

  • 字符串可以用.操作符链接起来

“hello”.“world” #等同于”helloworld” “hello” . ' ' . “world” #等同于’hello world' ‘hello world’ . “\n” #等同于"hello world\n"

  • 注意:链接运算符必须显示使用连接操作符(concatenation operator),而不是像其他一些语言 只需要把两个字符串放在一起就行。
  • 特殊的重复操作符,小写字母x,此操作符会将其左边的操作数与它本身重复连接,重复次数由右边的 操作数(某个数字)指定。例子:

“fred” x 3 #得到“fredfredfred” “barney” x (4+1) #得到“barneybarneybarneybarneybarney” 5 x 4.8 #相当于5乘以4,它会把4.8当做4,因为这里是小写字母x而不是*

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

  • Perl根据操作符来确定你需要的是数字还是字符串。如操作符(比如+号)需要的是数字,Perl会将操作 数视为数字;在操作符(比如.)需要字符串时,Perl便会将数视为字符串。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/usr/bin/perl
#Todo: concatenation operator
use 5.010;
printf "5*4.8\n";
printf 5 * 4.8 . "\n";
printf 5 x 4.8 . "\n";
printf "z" . 5*7 . "\n";

###Output
[root@Mo arvon_perl]# perl string_repetition
5*4.8
24
5555
z35

###Perl的内置警告信息

  • 从Perl的5.6版本开始,可以通过编译指令开启警告功能
1
2
#!/usr/bin/perl
use warnings;
  • 也可以在命令行上使用-w选项对要运行的程序开启警告功能

$ perl -w program.pl

  • 还可以在shebang行上指定命令行选项
1
#!/usr/bin/perl -w
  • 如果看不懂某个警告信息,可以利用diagnostics这个编译命令报告更为详尽的问题描述。在perdiag文档 中列有简要警告信息和详细诊断说明,该文档时理解diagnostics输出信息的最佳参考:
1
2
#!/usr/bin/perl
use diagnostics;	#会使程序变慢,如果熟悉,尽量不使用

###标量变量

  • 变量(variable)就是存储一个或多个值的容器的名称。而标量变量就是单单存储一个值的变量。变量的 名称在整个程序中保持不变,但它所持有的值是可以在程序运行时不断修改变化的。
  • 标量变量存储的是单个标量值。标量变量的名称是以$开头的,这个符号也称为魔符(sigil),然后是变 量Perl的标识符:由一个字母或下划线开头,后接多个字母、数字、下划线。标识符是区分大小写的:$Fred 和$fred是完全不同的变量。

$name $Name $NAME $a_very_long_variable_that_ends_in_i

  • Perl通过变量标识符的魔符来区分它是什么类型的变量。所以不管取什么名字,都不会和Perl自带的函数 或操作符的写法相冲突。$的确切意思是“取单个东西”或者“取标量”。
  • 给变量取个好名字,例如:$my_name or $myName

###标量的赋值(assignment)

  • 和其他程序语言差不多,Perl的赋值操作符为等号,等号的左边是变量名称,右边为某个表达式。
1
2
3
4
$fred = 17;
$barney = 'hello';
$barney = $fred+3;
$barney = $barney*2;

####双目赋值的操作符

  • 例子一
1
2
3
$fred = $fred + 5;	#相当于$fred += 5;
$barney = $barney * 3;	#相当于$barney *= 3;
$str = $str. " ";	#相当于$str .= "";
  • 例子二
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/usr/bin/perl
$fred = 1;
$fred = $fred + 5;
printf "now + 5 fred is " . $fred . "\n";
$fred += 2;
printf "then + 2 fred is " . $fred . "\n";
$str = 'hello';
$str = $str . " ";
print "the string \$str is " . $str . "\n";

###Output
root@Mo arvon_perl]# perl double.pl
now + 5 fred is 6
then + 2 fred is 8
  • 字符串中的标量变量内插
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/perl
$meal = "love";
$things = "arvon $meal mo";
print "$things\n";
$newThings = ' arvon ' . $meal . ' mo';
print 'now the $newThings is' . $newThings . "\n";

###Output[root@Mo arvon_perl]# perl varInsert.pl
arvon love mo
now the $newThings is arvon love mo
  • 如果变量从未被赋值过,就会用空字符串来替换
  • 如果只是打印这个变量值,则不必使用变量内插的方式:
1
2
print "$fred"
print $fred	#用这个比较好
  • 可以直接键入一些字符的代码点(code point),再通过chr()函数转换成对应字符,反过来我们可以通过 ord()函数把字符转换为代码点
1
2
$alef = chr( 0x05Do );
$codePoint = ord('?');

###操作符的优先级与结合性

  • 在复杂的表达式里,先执行哪个操作再执行哪个操作,取决于操作符的优先级。在Perl里乘法的优先级高于 加法,可以使用括号改变执行的优先级
  • 当两个优先级相同的操作符抢着使用三个操作数时,优先级便交由结合性解决:
1
2
3
4 ** 3 ** 2 #4 ** (3 ** 2),得4 ** 9,向右结合
72 / 12 / 3#(72 / 12) / 3,得6 / 3,向左结合
36 / 6 * 3	#(36 / 6) * 3

###比较操作符

  • perl的比较操作符类似于代数系统:<,<=,==,>=,>,!=。这些操作符的返回值要么是true要么是false。
  • 字符串比较时,使用lt、le、eq、ge、gt、ne。注意:字符在ASCII编码中的顺序并不总是对应于字 符本身意义上的顺序。

##控制结构 ###if控制结构 ####例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/perl
#$name = 'fred';
$name = 'Nfred';
if ($name eq "fred"){
    print "'$name' is 'fred' in\n";
}
else{
    print "'$name' is not 'fred' is $name\n";
}

####布尔值

  • 任何标量值都可以成为if控制结构里的判断条件。如果把表达式返回的真假值保存到变量中,那在判断时可以 直接检查该变量的值,读起来也方便:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/perl
#$name = 'fred';
$name = 'Nfred';
if ($name eq "fred"){
    print "'$name' is 'fred' in\n";
}
else{
    print "'$name' is not 'fred' is $name\n";
}

###Output
[root@Mo arvon_perl]# perl Boolean_value.pl
hello, world
  • Perl和其他语言不同,Perl并没有专用的“布尔(boolean)”数据类型,它是靠一些简单的规则来判断的:
  • 如果是数字,0为假,所有其他数字都为真
  • 如果是字符串,空字符串('')为假;所有其他字符串为真。
  • 如果既不是数字也不是字符串,那就先转换成数字或字符串再进行判断。

###获取用户输入

  • 用户输入的例子
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/usr/bin/perl
print "Input something please: ";
$line = <STDIN>;
if ($line eq "\n"){
    print "That was just a blank line!\n";
}
else{
    print "That line of input was: $line";
}

###Output
[root@Mo arvon_perl]# perl stdin01.pl
Input something please:
That was just a blank line!
[root@Mo arvon_perl]# perl stdin01.pl ]
Input something please: hello
That line of input was: hello

###chomp操作符

  • chomp()操作符只能用于单个变量,且该变量的内容必须为字符串,如果该字符串的末尾是换行符,chomp() 的任务就是去掉它。
1
2
3
4
5
6
7
8
#!/usr/bin/perl
$text = "a line of text\n";     #or input by <STDIN>
chomp($text);   #remove the \n
print $text;

###Output
[root@Mo arvon_perl]# perl chompTraining.pl
a line of text[root@Mo arvon_perl]#
  • 处理字符串变量
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/perl
chomp($text = <STDIN>); #读入文字,略过最后的换行符
#$text = <STDIN>;       #等同于上面的写法
#chomp($text):
print $text;

###Output
[root@Mo arvon_perl]# perl chompTraining02.pl
hello,world
hello,world[root@Mo arvon_perl]#

###while控制结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/usr/bin/perl
$count = 0;
while ($count <  10){
    $count += 2;
    print "Now the number is $count\n";
}

###Output
[root@Mo arvon_perl]# perl whileCount.pl
Now the number is 2
Now the number is 4
Now the number is 6
Now the number is 8
Now the number is 10

###undef值

  • 我们未赋值时就用到了某个不存在标量变量,并不会让程序停止运行,当成数字使用,它会表现的像0;当 做字符串使用,它会表现的像空字符串。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/perl
#累加奇数
$n = 1;
while ($n < 10){
    $sum += $n;
    $n += 2;#准备奇数
}
print "The total was $sum.\n"

###Output
[root@Mo arvon_perl]# perl accumulation.pl
The total was 25.

###definded函数

  • 行输入操作符有时候会返回undef。要判断某个字符串是undef而不是空字符串,可以使用defined 函数。如果是undef,该函数返回假,否则返回真:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/perl
$madonna = <STDIN>;
if (defined($madonna)){
    print "The input was $madonna";
}
else{
    print "No input available\n";
}
#$madonna = undef;

###Output
[root@Mo arvon_perl]# perl undef01.pl
No input available
[root@Mo arvon_perl]# perl undef01.pl
Mo
The input was Mo
[root@Mo arvon_perl]# perl undef01.pl

The input was

##列表和数组

  • 如果Perl的标量代表单数(singular),那么列表和数组就表示复数(plural)。
  • 列表(list)是标量的有序集合,而数组(array)则是存储列表的变量。列表指的是数据,而数组指的是变 量。列表里的值不一定放在数组里,但每个数组变量都包含一个列表(即便是不含任何元素的空列表。
  • 数组或列表中的每个元素 (element)都是单独的标量变量,拥有独立的标量值。这些值是有序的,从开始到 终止元素的先后次序是固定的。

###访问数组中的元素

  • Example one
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/usr/bin/perl
use 5.010;
#print "Hello world\n";
$fred[0] = "Hello";
$fred[1] = "My";
$fred[2] = "Name";
print "$fred[0]\n";

###Output
>arvon@Mo:~/arvon_perl> perl array.pl
Hello

###特殊的数字索引

  • Example two
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/perl
use 5.010;
$rocks[0] = 'hello';
$rocks[1] = 'list';
$rocks[2] = 'array';
$rocks[3] = 'element';
$rocks[4] = 'four';
$rocks[9] = 'nine';
#
$end = $#rocks;
print "\$end is $end\n";
#
$number_of_rocks = $end + 1;
print "The number is $number_of_rocks\n";
#
$rocks[ $#rocks ] = 'hard rodk';

###Output
arvon@Mo:~/arvon_perl> perl array_print.pl
$end is 9
The number is 10

###列表直接量

  • 列表直接量(list literal),可以由圆括号内用逗号隔开的一组数据表示,而这些数据就称为元素。 for example
1
2
3
4
5
6
7
8
(1, 2, 3)  #(1, 2, 3,)相同的逗号会被忽略
("fred", 4.5)   #两个元素,'fred'和4.5
()  #空列表,0个元素
(1..100)    #100个整数组成的列表
(1..5)  #..是范围操作符(range operator)
(1.7..5.7)  #同上,但两个数字的小数部分会被去掉
(5..1)  #表示空列表,只能正向计数
($m..$n)    #由$m和$n决定

###qw简写

  • 在perl程序中,经常会需要建立简单的单词列表。使用qw简写,可以省去键入的引号。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/perl
use 5.010;
("Mo", "have", "rose", "you", "known");
#
qw( Mo have rose you known );
#
qw(Mo
hava    rose
you known);
#
qw(
    Mo
    have
    rose
    you
    known
);
#
qw! Mo have rose you known!;
qw/ Mo have rose you known/;
qw# Mo have rose you known#;

###列表的赋值

  • 和标量赋值一样,列表值可以被赋值给变量
1
2
3
4
#!/usr/bin/perl
use 5.010;
($fred, $barney, $dino) = ("flintstone", "rubble", undef);
#左侧列表中的三个变量会依次被赋予右侧列表中对应的值,相当于分别做了三次独立的赋值操作;

###pop和push操作符

  • 要增加元素到数组尾端时,只要将它存放到更高索引的新位置就可以了。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/perl
@array = 5..9;
$mo = pop(@array);
printf "now \$mo is $mo\n";
$arvon = pop(@array);
printf "now \$arvon is $arvon\n";
push(@array, 0);
printf "now \@array is @array\n";
push@array,3;
printf "now \@array is @array\n";
push@array,"Hello";
printf "now \@array is @array\n";
@newOne = qw/ my name is arvon /;
print "@newOne\n";
###Output
arvon@Mo:~/arvon_perl> perl assignment_array.pl
now $mo is 9
now $arvon is 8
now @array is 5 6 7 0
now @array is 5 6 7 0 3
now @array is 5 6 7 0 3 Hello
my name is arvon

###shift和unshift操作符

  • 相反,unshift和shift操作符是对数组的开头进行处理
 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
#!/usr/bin/perl
use 5.010;
@array = qw/ why are you so diao /;
$one = shift@array;#$one is "why", @array = are you so diao
print "$one is not @array\n";
$two = shift(@array);#$two is "are", @array = you so diao
print "$two is not @array\n";
$three = shift@array;#$three is "you", @array= so diao
print "$three is not @array\n";
##
unshift(@array, 4);
print "Now \@array is @array\n";
unshift(@array, 5);
print "Now \@array is @array\n";
@others = 1..3;
unshift @array, @others; #@array变成了(1, 2, 3, 4, 5, )
print "\@others is @others, But now \@array is already @array";

###Output
arvon@Mo:~/arvon_perl> perl unshift_str.pl
why is not are you so diao
are is not you so diao
you is not so diao
Now @array is 4 so diao
Now @array is 5 4 so diao
@others is 1 2 3, But now @array is already 1 2 3 5 4 so diao

###splice操作符

  • push-pop和shift-unshift操作符都是对数组首尾进行操作的,中间的话就用splice
  • Example one
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/perl
use 5.010;
@array = qw( pebbles dino fred barney betty );
@removed = splice @array, 2;#在原来的数组中删掉fred及其后的元素
#@removed变成qw(fred barney betty)
#而原来的@array则变成qw(pebbles dino)
print "\@array now is @array\n";
print "\@removed is @removed\n";

###Output
arvon@Mo:~/arvon_perl> perl splice_string.pl
@array now is pebbles dino
@removed is fred barney betty
  • Example two
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/usr/bin/perl
use 5.010;
@array = qw( pebbles dino fred barney betty );
#@removed = splice @array, 2;#在原来的数组中删掉fred及其后的元素
##@removed变成qw(fred barney betty)
##而原来的@array则变成qw(pebbles dino)
#print "\@array now is @array\n";
#print "\@removed is @removed\n";
#@removed = splice @array, 1, 2;
##This time @removed is (pebbles, barney, betty )
@removed = splice @array, 1, 0, qw(wilema);
##Just known @array is became (pebbles wilema dino fred barney betty)
print "now \@removed is @removed, and \@array is @array.\n"

###Output
arvon@Mo:~/arvon_perl> perl splice_string.pl
now @removed is , and @array is pebbles wilema dino fred barney betty.

###字符串的内插

  • 和标量一样,数组的内容同样可以被内插到双引号中。内插时,会在数组的各个元素之间自动添加分隔用的空格
1
2
3
4
5
6
7
8
#!/usr/bin/perl
use 5.010;
@rocks = qw/ flintstone slate rubble /;
print "Quartz @rocks limestone\n"

###Output
arvon@Mo:~/arvon_perl> perl array_one.pl
Quartz flintstone slate rubble limestone
  • Example for index_expression
1
2
3
4
5
6
7
8
#!/usr/bin/perl
use 5.010;
@fred = qw(eating rocks is wrong);
$fred = "right";
print "This is $fred[3]\n";     #just right
print "This is ${fred}[3]\n";   #wrong
print "This is $fred"."[3]\n";  #wrong
print "This is $fred\[3]\n";    #still wrong

##后续下一篇,太长了不方便查阅

  • So, Let’s go