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

数组的最后一个元素索引是$#XXXX是数组变量名,不过这个用起来比较麻烦,用的更多的是负值索引:

#!/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个参数:

  1. 目标数组;
  2. 要操作的开始元素的索引;
  3. 元素长度,可选,如果不指定,则默认长度到最后一个元素为止;
  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基础的主要内容,如果未能解决你的问题,请参考以下文章

Perl 标量

Perl 变量:标量变量

6-Perl 标量

Perl基础教程--精华篇

(转)Perl基础教程一

如何区分 Perl 中的数字标量和字符串标量?