Perl基础
Posted jiangwei0512
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl基础相关的知识,希望对你有一定的参考价值。
综述
官网
Perl语言官网:<The Perl Programming Language - www.perl.org>。
简述
Perl语言的应用范围很广,除CGI以外,Perl被用于图形编程、系统管理、网络编程、金融、生物以及其他领域。由于其灵活性,Perl被称为脚本语言中的瑞士军刀。
Perl语言的优点:
- 相比C、Pascal这样的“高级”语言而言,Perl语言直接提供泛型变量、动态数组、Hash表等更加便捷的编程元素;
- Perl具有动态语言的强大灵活的特性,并且还从C/C++、Basic、Pascal等语言中分别借鉴了语法规则,从而提供了许多冗余语法;
- 在统一变量类型和掩盖运算细节方面,Perl做得比其他高级语言(如:Python)更为出色;
- 由于从其他语言大量借鉴了语法,使得从其它编程语言转到Perl语言的程序员可以迅速上手写程序并完成任务,这使得Perl语言是一门容易用的语言;
- Perl语言是可扩展的,我们可以通过CPAN(Comprehensive Perl Archive Network)中心仓库找到很多我们需要的模块;
- Perl语言的
mod_perl
模块允许Apache Web服务器使用Perl解释器。
Perl语言的缺点:
- Perl语言的灵活性和“过度”的冗余语法,使得许多Perl程序的代码令人难以阅读和维护(变成了“Write-Only”);
- Perl语言随意的特点,可能会导致一些Perl程序员遗忘语法,以至于不得不经常查看Perl手册;
建议的解决方法是在程序里使用use strict;
以及use warnings;
,并统一代码风格,使用库,而不是自己使用“硬编码”。
Perl擅长处理整体来说“约有90%与文字处理有关,10%与其它事务有关”的问题。
Perl是编写小型CGI的最佳语言。
Perl的注释用#
,没有块注释。
Perl程序并不需要变量声明的部分。
源代码使用Unicode书写的话,需要使用use utf8;
,除非有明确的原因不加,否则就应该用上。
下载和安装
下载Perl编译环境,需要注意的是Windows版本下有两种编译环境:
就目前的使用来看没法确定差别,暂时下载Strawberry Perl,因为它不需要账户就可以下载。下载之后安装,安装之后可以通过如下的方式查看:
表示已经安装成功。
HelloWorld
代码位于Basic\\HelloWorld.pl:
#!/usr/bin/perl
use utf8;
print "Hello, World!\\n";
执行的结果:
E:\\Gitee\\perl\\Code\\Basic>HelloWorld.pl
Hello, World!
E:\\Gitee\\perl\\Code\\Basic>
参考书
《Learning Perl》(《Perl语言入门》)
《Internediate Perl》(没中文)
《Mastering Perl》(《精通Perl》)
《Programming Perl》(《Perl语言编程》)
其它
一般P大写的Perl表示程序语言,P小写的perl表示实际编译并运行的解释器。
基本语法
标量数据
标量是Perl里面最简单的一种数据类型,分为数字和字符串(其实还有undef
)。
- 数字分为整型和浮点型,但是在Perl内部都是浮点型,整型也是由浮点型表示的。
- 字符串可以用单引号和双引号,双引号中的反斜杠更为强大,可以转义许多控制字符:
- 单引号中的
\\n
是两个字符; - 双引号中的
\\n
是换行符; - 诸如此类的差异。
- 单引号中的
数字和字符串会自动转换,如何转换主要依赖于操作符。
字符串操作
连接操作用.
:
#!/usr/bin/perl
use utf8;
use warnings;
print "hello" . " " . "world"; # 点号用来连接
字符串重复使用x
,其实就是小写的x字符:
#!/usr/bin/perl
use utf8;
use warnings;
print "hello" x 3;
注意下面的例子:
#!/usr/bin/perl
use utf8;
use warnings;
print 5 x 4.8 # 打印结果5555
因为使用了x
所以是字符串重复操作,而该操作左侧必须是字符串,所以5被转换成了"5",右侧的数字又会被取整,所以变成了4,最终就输出了"5555"。当重复次数小于1时会返回空字符串:
#!/usr/bin/perl
use utf8;
use warnings;
print "hello" x 0.1; # 打印为空
标量变量
标量变量是单单存储一个值的变量。
标量变量名以美元符号开头。
#!/usr/bin/perl
use utf8;
use warnings;
$hello = "Hello"; # 定义变量
$space = " "; # 定义变量
$world = "world"; # 定义变量
print $hello, $space, $world; # print后面的参数可以用逗号隔开,实际上是个列表
变量可以内插,即把字符串内出现的所有标量变量替换成变量当前的值:
#!/usr/bin/perl
use utf8;
use warnings;
$hello = "hello";
print "$hello world"; # 变量内插
如果变量没有被赋值,就会用空字符串来替换。
如果只要打印变量值,则不需要使用变量内插:
#!/usr/bin/perl
use utf8;
use warnings;
$hello = "hello";
print $hello; # 变量内插,这种情况可以不需要要双引号,不过也可以加
变量内插只适用于双引号:
#!/usr/bin/perl
use utf8;
use warnings;
$hello = "hello";
print "$hello"; # 打印hello
print '$hello'; # 打印$hello,多一个$
内插的变量会以最长且合法的方式获取:
#!/usr/bin/perl
use utf8;
use warnings;
$hello = "hello";
$helloworld = "hello world";
print "$helloworld";
如果想使用$hello
,可以用大括号括起来:
#!/usr/bin/perl
use utf8;
use warnings;
$hello = "hello";
$helloworld = "hello world";
print "$helloworld"; # 使用
代码点创建字符
chr()
函数可以将数字转换成字符:
#!/usr/bin/perl
use utf8;
use warnings;
print chr(0x30); # 0的ASCII是0x30,所以这里打印0
print chr(0x31); # 1的ASCII是0x30,所以这里打印1
ord()
执行相反的操作:
#!/usr/bin/perl
use utf8;
use warnings;
print ord('0'); # 打印48
布尔值
- 如果是数字,0为假,其它为真;
- 如果是字符串,空字符串(
""
或''
)为假,其它为真(有例外,见下面); - 如果既不是数字也不是字符串,那就先转换成数字或者字符串再行判断;
- 字符串’0’和数字0是同一个标量值,所以都为假:
#!/usr/bin/perl
use utf8;
use warnings;
if (0)
print "0 is true\\n";
else
print "0 is false\\n"; # 执行到这里
if ('0')
print "'0' is true\\n";
else
print "'0' is false\\n"; # 执行到这里
if ('')
print "'' is true\\n";
else
print "'' is false\\n"; # 执行到这里
undef
也是假
#!/usr/bin/perl
use utf8;
use warnings;
if (undef)
print "undef is true\\n";
else
print "undef is false\\n"; # 执行到这里
如果有else if,则使用elsif
,注意少一个e
。
前面的布尔值可用于if
,还可以用于while
:
#!/usr/bin/perl
use utf8;
use warnings;
$count = 2;
while ($count)
$count -= 1;
print "count: $count\\n";
获取用户输入
“行输入”操作符是<STDIN>
:
#!/usr/bin/perl
use utf8;
use warnings;
$input = <STDIN>;
print "input: ", $input;
<STDIN>
默认(通过$/
存放换行符)在遇到换行符之后退出。
<STDIN>
返回的字符中包含换行符。
chomp()
函数作用于字符串,用于去掉字符串末尾的换行符(注意只去掉行尾)并返回:
#!/usr/bin/perl
use utf8;
use warnings;
$input = <STDIN>;
chomp $input;
print "input: ", $input;
注意chomp()
是有返回值的,所以下面的代码跟上面的代码不同:
#!/usr/bin/perl
use utf8;
use warnings;
$input = <STDIN>;
print "input: ", chomp $input; # 打印input: 1
input: 1
表示chomp()
去掉的字符数,这里就是1个换行符。
$/
记录了分隔符,它默认就是换行符\\n
, 设置这个操作符会影响chomp()
,chomp()
默认是去掉行尾的\\n
,当设置了$/
,chomp()
会去掉$/
设置的符号。
local $/ = "END";
上述的语句之后chomp()
会将END
认为换行符:
#!/usr/bin/perl
use utf8;
use warnings;
use 5.010;
local $/ = "END";
while (<>)
chomp;
print "$_\\n";
执行上述的代码结果:
E:\\Gitee\\perl\\Code\\Basic>Input.pl
nihao
END
nihao
只有当输入END
才会往下执行。
undef
在首次赋值前,变量的初始值就是特殊的undef
。
- 当作为数字时,它表现得像0;
- 当作为字符串时,它表现得像空字符串。
- 但
undef
即不是数字也不是字符串,它是另一种类型的标量值。
defined()
函数用于判断某个变量是undef
还是空字符串,如果是undef
则返回假:
#!/usr/bin/perl
use utf8;
use warnings;
$var;
if (defined($var))
print "defined\\n";
else
print "undef\\n" # 执行到这里
$var = '';
if (defined($var))
print "defined\\n"; # 执行到这里
else
print "undef\\n"
运算符
比较操作符
比较 | 数字 | 字符串 |
---|---|---|
相等 | == | eq |
不等 | != | ne |
小于 | < | lt |
大于 | > | gt |
小于或等于 | <= | le |
大于或等于 | >= | ge |
逻辑运算符
表格示例中我们设置变量$a
为true,$b
为false。
运算符 | 描述 |
---|---|
and | 逻辑与运算符符。如果两个操作数都为true,则条件为true。 |
&& | c语言风格的逻辑与运算符符。如果两个操作数都为true,则条件为true。 |
or | 逻辑或运算符。如果两个操作数中有任意一个非零,则条件为true。 |
|| | c语言风格逻辑或运算符。如果两个操作数中有任意一个非零,则条件为true。 |
not | 逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将使其为false。 |
两种风格都可以使用。
列表和数组
在Perl里代表复数的是列表和数组。
列表是标量的有序集合,而数组则是存储列表的变量。
列表指的是数据,而数组指的似乎变量。每个数组变量都一定包含一个列表。
用于列表和数组的操作有许多是相同的,后面一般使用数组这个词。
数组是有序的。
数组可以包含数字、字符串、undef
和它们的组合。
数组的每个元素都是单独的标量变量(可以需要使用$
):
#!/usr/bin/perl
use utf8;
use warnings;
@list = (); # 定义空的数组
$list[0] = 1; # 数组中的元素赋值
$list[1] = 2;
$list[2] = 3;
print @list;
@list
中的@
表示引用整个数组,在定义和使用整个数组时需要用到。
数组的名字空间和标量的名字空间是分开的,所以程序中可以取相同的名字,不过最好不要这么做。
#!/usr/bin/perl
use utf8;
use warnings;
$Var = 1;
print $Var; # 打印1
@Var = (1, 2, 3);
print @Var; # 打印123
访问元素
如果对超过数组尾端的元素进行赋值,则数组会自动扩大,中间没有赋值的元素就是undef
。
数组的最后一个元素索引是$#XX
,XX
是数组变量名,不过这个用起来比较麻烦,用的更多的是负值索引:
#!/usr/bin/perl
use utf8;
use warnings;
@list = (); # 空的数组
$list[0] = 1; # 数组中的元素赋值
$list[1] = 2;
$list[2] = 3;
print $list[$#list]; # 3
print $list[-1]; # 3
print $list[-2]; # 2,也可以使用-2这种负值索引
一般情况下值用-1
来访问最后的元素,其它的负值不怎么用。
数组直接量
数组直接量用小括号包含,中间用逗号隔开成员,还可以使用...
:
#!/usr/bin/perl
use utf8;
use warnings;
print (1, 2, 3, 4, 5); # 打印12345
print (1...5); # 打印12345
print (5...1); # 打印空,因为...前后必须是向上计数的
字符串直接量:
#!/usr/bin/perl
use utf8;
use warnings;
print ("hello", " ", "world");
为了避免键入太多的引号,可以使用qw()
函数:
#!/usr/bin/perl
use utf8;
use warnings;
@list = qw(hello world);
foreach $value (@list)
print $value;
print "\\n"
qw()
会将内部元素转换为字符串,其中的空白符是隔断,并且最终会被抛弃。
数组元素的赋值:
#!/usr/bin/perl
use utf8;
use warnings;
($name, $age) = ("Jake", 19);
print "The name is $name\\n";
print "THe age is $age\\n";
操作函数
push()
函数将新元素添加到数组尾部。
pop()
函数取出数组最后一个元素并将其作为返回值返回。如果数组本来就是空的,则返回undef
。
shift()
函数将新元素添加到数组开头。
unshift()
函数取出数组第一个元素并将其作为返回值返回。
splice()
函数在数组中间添加或移除某些元素。它接收4个参数:
- 目标数组;
- 要操作的开始元素的索引;
- 元素长度,可选,如果不指定,则默认长度到最后一个元素为止;
- 替换用的数组,可选,如果不指定,就是删除目标数组的数据。
如果元素长度为0,替换用的数组存在,则相当于添加数组。
上述的函数都会改变数组本身。
reserve()
函数返回次序相反的数组,但是不改变原数组。
sort()
函数返回排序之后的数组,但是不改变原数组。
上述两个函数不改变数组本身。
字符串中的数组内插
数组内插也可以在字符串中使用,所以需要注意下面的情况:
#!/usr/bin/perl
use utf8;
use warnings;
@google = qw(hello google);
print "perl@google.com\\n"; # 打印perlhello google.com
print "perl\\@google.com\\n"; # 打印perl@google.com
foreach/each
foreach
用于遍历数组,它包含两个参数,第一个是数组变量,第二个是数组本身,它需要用括号括起来:
#!/usr/bin/perl
use utf8;
use warnings;
@name = qw(Jack Jimmy John);
foreach $n (@name)
print "The name is $n\\n";
如果省略数组变量,则默认用$_
替代:
#!/usr/bin/perl
use utf8;
use warnings;
@name = qw(Jack Jimmy John);
foreach (@name)
print "The name is $_\\n";
更特殊的是,即使print()
函数什么也不带,也会打印$_
:
#!/usr/bin/perl
use utf8;
use warnings;
@name = qw(Jack Jimmy John);
foreach (@name)
print;
# 最终打印JackJimmyJohn
each
以前只能用于哈希,但是现在也能用于数组,它返回数组中下一个元素对应的键值对(对于数组就是索引和元素值):
#!/usr/bin/perl
use utf8;
use warnings;
@name = qw(Jack Jimmy John);
while (($index, $value) = each @name)
print "$index: $value\\n";
数组输入
标量输入是一行,以回车键结尾;数组输入是所有行,以EOF
结束(Linxu中是Ctrl+D
,Windows中是Ctrl+Z
):
#!/usr/bin/perl
use utf8;
use warnings;
chomp(@line = <STDIN>);
print @line;
chomp()
可以去掉每一行末尾的换行符。
子程序
子程序其实就是函数。
使用关键字sub
定义函数:
#!/usr/bin/perl
use utf8;
use warnings;
sub add
$n += 1;
print "value: $n\\n";
add # 1
add # 2
add # 3
&add # 4,注意这里使用了&
从这里也可以看到$n
实际上是全局的。
注意这里的&add
前面的&
,这里是先定义了函数,然后调用,所以Perl能够识别到函数,可以不用&
,但是这可能跟Perl内置函数冲突,所以最好还是加上&
。
返回值
在Perl中所有函数都有返回值,返回的是最后一次运算的结果(不管是什么):
#!/usr/bin/perl
use utf8;
use warnings;
sub add
$n += 1;
print &add; # 1
print &add; # 2
这里$n += 1;
的计算结果就是返回值。注意下面的代码:
#!/usr/bin/perl
use utf8;
use warnings;
sub add
$n += 1;
print $n;
print &add; # 1
print &add; # 1
这里的两个print &add;
打印的值都是1,原因是函数add()
返回的是print()
的结果,后者的返回值一般就是1。
返回值也可以是非标量。
返回值也可以使用return
操作符,尤其是要在函数中间返回的时候,不过这个时候return
后面需要加返回值。如果什么也不写,则在标量上下文返回undef,在列表上下文返回空列表。
参数
函数可以有参数,用小括号括起来。参数其实是一个列表,在函数中用@_
访问,但是要使用其中的元素,还是应该用$_[x]
:
#!/usr/bin/perl
use utf8;
use warnings;
sub sum (a, b)
foreach (@_)
print "$_\\n";
# 打印1和2
$sum = $_[0] + $_[1];
print &sum(1, 2); # 打印3
@_
在标量上下文中也可以是标量,表示参数的个数:
#!/usr/bin/perl
use utf8;
use warnings;
sub max
if (@_ != 2)
print "Invalid parameter\\n";
return;
if ($_[0] < $_[1])
print "2ed is bigger\\n";
elsif ($_[0] > $_[1])
print "1st is bigger\\n";
else
print "equal\\n"
&max(1); # Invalid parameter
&max(1, 2); # 2ed is bigger
&max(1, 2, 3); # Invalid parameter
参数也可以通过shift
传递:
#!/usr/bin/perl
use utf8;
use warnings;
use 5.010;
sub print_param
$first = shift;
$sencond = shift;
say $first;
say $sencond;
&print_param(1, 2);
每调用一次shift
就可以用参数赋值一次。
私有变量
函数中的变量一般是全局变量,如果要使用私有变量,需要使用my
操作符:
#!/usr/bin/perl
use utf8;
use warnings;
sub add
my $n += 1;
print &add; # 1
print &add; # 1
由于$n
是私有变量,所以每次调用函数都会重启被初始化为undef
,然后加上1,就变成了1,最终两次返回都是1。
如果想要把私有变量保存起来(类似于c语言中的statisc
),则需要使用state
操作符:
#!/usr/bin/perl
use utf8;
use warnings;
use 5.010; # 注意state是在5.10版本引入的,所以要加上
sub add
state $n = 0;
$n += 1;
print &add; # 1
print &add; # 2
my不会改变赋值时的上下文:
my ($num) = @_; # 列表上下文,和 ($num) = @_; 相同
my $num = @_; # 标量上下文,和 $num = @_; 相同
在my
操作符不加括号时,只能用来声明单个词法变量:
my $fred, $barney; # 没有将$barney私有
my(以上是关于Perl基础的主要内容,如果未能解决你的问题,请参考以下文章