-

Perl - 介绍

Perl是最初为文本处理开发的通用编程语言,现在用于各种任务,包括系统管理,Web开发,网络编程,GUI开发等。

什么是Perl?

“PC杂志”宣布,Perl在“开发工具”类别中获得1998年技术卓越奖的入围。

Perl特性

Perl和Web

Perl被解释

Perl是一种解释语言,这意味着您的代码可以按原样运行,而不需要编译阶段来创建非便携式可执行程序。

传统的编译器将程序转换为机器语言。当您运行Perl程序时,首先将其编译成一个字节代码,然后将其转换为程序运行的机器指令。所以它不完全一样的shell或Tcl,这是严格解释没有中间的表示。

它也不像大多数版本的C或C ++,它们直接编译成机器依赖的格式。它是在两者之间,以及Pythonawk以及Emacs的.elc文件。

Perl - 环境

在线运行

我们已经在线设置了Perl Programming环境,以便您可以在线编译和执行所有可用的示例。你可以学习的同时,在线验证程序。随意修改任何示例并在线执行。

使用我们的在线编译器可在尝试下面的例子CodingGround

#!/usr/bin/perl

# This will print "Hello, World"
print "Hello, world
";

对于本教程中给出的大多数示例,您将在右上角的网站代码部分找到一个Try it选项,该部分将带您进入在线编译器。所以只是利用它,享受你的学习。

在开始编写Perl程序之前,让我们了解如何设置Perl环境。Perl可在各种平台上使用 -

这更可能是您的系统安装了perl。只需尝试在$ prompt下给出以下命令 -

$perl -v

如果您的机器上安装了perl,那么您将收到以下消息:

This is perl 5, version 16, subversion 2 (v5.16.2) built for i686-linux

Copyright 1987-2012, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

如果您没有安装perl,请转到下一节。

获取Perl安装

Perl官方网站上提供了最新和最新的源代码,二进制文件,文档,新闻等。

Perl官方网站 - https://www.perl.org/

您可以从以下站点下载Perl文档。

Perl文档网站 - https://perldoc.perl.org

安装Perl

Perl分布可用于各种平台。您只需要下载适用于您的平台的二进制代码并安装Perl。

如果您的平台的二进制代码不可用,则需要一个C编译器手动编译源代码。编译源代码在安装中需要的功能选择方面提供更多的灵活性。

以下是在各种平台上安装Perl的快速概述。

Unix和Linux安装

以下是在Unix / Linux机器上安装Perl的简单步骤。

$tar -xzf perl-5.x.y.tar.gz
$cd perl-5.x.y
$./Configure -de
$make
$make test
$make install

注意 - 这里$是一个Unix提示符,您键入命令时,因此请确保在键入上述命令时不输入$。

这将在标准位置/ usr / local / bin中安装Perl ,其库安装在/ usr / local / lib / perlXX中,其中XX是您正在使用的Perl版本。

发出make命令后需要一段时间来编译源代码安装完成后,您可以在$ prompt下发出perl -v命令,以检查perl安装。如果一切都很好,那么它将显示如上所示的消息。

Windows安装

以下是在Windows机器上安装Perl的步骤。

Macintosh安装

为了创建您自己的Perl版本,您需要“make”,这是通常随Mac OS安装DVD提供的Apple开发人员工具的一部分。您不需要最新版本的Xcode(现在收取)为了安装make。

以下是在Mac OS X机器上安装Perl的简单步骤。

$tar -xzf perl-5.x.y.tar.gz
$cd perl-5.x.y
$./Configure -de
$make
$make test
$make install

这将在标准位置/ usr / local / bin中安装Perl ,其库安装在/ usr / local / lib / perlXX中,其中XX是您正在使用的Perl版本。

运行Perl

以下是启动Perl的不同方式。

互动翻译

您可以通过从命令行启动交互式解释器,直接输入perl并开始编码。您可以从Unix,DOS或任何其他系统中执行此操作,该系统为您提供命令行解释器或shell窗口。

$perl  -e <perl code>           # Unix/Linux

or 

C:>perl -e <perl code>          # Windows/DOS

以下是所有可用命令行选项的列表 -

没有 选项和说明
1。 -d [:debugger]

在调试器下运行程序

2。 -Idirectory

指定@ INC /#include目录

3。 -T

可以进行污点检查

4。 -t

使污染警告

5。 -U

允许不安全的操作

6。 -w

启用许多有用的警告

7。 -W

启用所有警告

8。 -X

禁用所有警告

9。 -e程序

运行Perl脚本作为程序发送

10。 文件

从给定的文件运行Perl脚本

命令行脚本

Perl脚本是一个文本文件,它保留perl代码,并且可以通过在应用程序中调用解释器在命令行中执行,如下所示 -

$perl  script.pl          # Unix/Linux

or 

C:>perl script.pl         # Windows/DOS

综合开发环境

您也可以从图形用户界面(GUI)环境运行Perl。所有您需要的是您的系统上支持Perl的GUI应用程序。您可以下载Padre Perl IDE如果您熟悉Eclipse ,还可以使用Eclipse插件EPIC - Perl Editor和 Eclipse。

在进入下一章之前,请确保您的环境设置正确并且工作正常。如果您无法正确设置环境,那么您可以从系统管理员处获取帮助。

后续章节中给出的所有示例已使用Linux上CentOS的v5.16.2版本执行。

Perl - 语法概述

Perl借用许多语言的语法和概念:awk,sed,C,Bourne Shell,Smalltalk,Lisp甚至是英文。然而,语言之间有一些明确的区别。本章旨在帮助您快速掌握Perl中预期的语法。

Perl程序由一系列的声明和语句组成,从顶部到底部运行。循环,子程序和其他控制结构允许您在代码中跳转。每个简单的语句都必须以分号(;)结尾。

Perl是一种自由形式的语言:您可以格式化和缩进它,但您喜欢。空格主要用于分离标记,不像Python这样的语言,它是语法的重要组成部分,或Fortran,它不重要。

第一个Perl程序

交互式模式编程

您可以在命令行中使用带有-e选项的Perl解释器,从而可以从命令行执行Perl语句。让我们尝试一下$ prompt,如下所示:

$perl -e "print "Hello World
""

这个执行将产生以下结果 -

Hello, world

脚本模式编程

假设您已经在$提示符下,我们使用vi或vim编辑器打开一个文本文件hello.pl,并将以下行放在文件中。

#!/usr/bin/perl

# This will print "Hello, World"
print "Hello, world
";

这里/ usr / bin / perl是实际的perl解释器二进制文件。在执行脚本之前,请确保更改脚本文件的模式并执行授权,通常0755的设置可以完美地运行,最后执行以下脚本:

$chmod 0755 hello.pl
$./hello.pl

这个执行将产生以下结果 -

Hello, world

您可以使用括号作为函数参数,也可以根据您的个人口味省略它们。他们只是偶尔要求澄清优先权问题。以下两个语句产生相同的结果。

print("Hello, world
");
print "Hello, world
";

Perl文件扩展名

可以在任何普通的简单文本编辑器程序中创建一个Perl脚本。有各种类型的平台可以使用几个程序。有许多程序设计可供在网上下载的程序员使用。

作为Perl约定,必须使用.pl或.PL文件扩展名保存Perl文件,以便将其视为功能正常的Perl脚本。文件名可以包含数字,符号和字母,但不能包含空格。在空格的位置使用下划线(_)。

Perl中的注释

任何编程语言的注释都是开发者的朋友。注释可用于使程序用户友好,并且它们被解释器简单地跳过,而不影响代码功能。例如,在上述程序中,以散列开始的行是注释。

简单地说Perl中的注释开头是哈希符号,并运行到行尾 -

# This is a comment in perl

以=开头的行被解释为嵌入式文档(pod)的一部分的开始,直到下一个= cut的所有后续行被编译器忽略。以下是这个例子 -

#!/usr/bin/perl

# This is a single line comment
print "Hello, world
";

=begin comment
This is all part of multiline comment.
You can use as many lines as you like
These comments will be ignored by the 
compiler until the next =cut is encountered.
=cut

输出结果如下 -

Hello, world

Perl中的空白

Perl程序不关心空白。以下程序工程完全正常 -

#!/usr/bin/perl

print       "Hello, world
";

但如果空格在引用的字符string内,那么它们将按原样打印。例如 -

#!/usr/bin/perl

# This would print with a line break in the middle
print "Hello
          world
";

输出结果如下 -

Hello                                                                                        
          world

解释器在引号之外使用时,所有类型的空格,标签,换行符等同。一行只包含空格(可能带有注释)的行被称为空白行,Perl完全忽略它。

Perl中的单和双引号

您可以在文字字符string周围使用双引号或单引号,如下所示:

#!/usr/bin/perl

print "Hello, world
";
print "Hello, world
";

输出结果如下 -

Hello, world
Hello, world
$

单引号和双引号有重要的区别。只有双引号插入变量和特殊字符(如换行符 n),而单引号不插入任何变量或特殊字符。检查下面的例子,我们使用$ a作为一个变量存储一个值,然后打印该值 -

#!/usr/bin/perl

$a = 10;
print "Value of a = $a
";
print "Value of a = $a
";

输出结果如下 -

Value of a = 10
Value of a = $a
$

“这里”文件

您可以非常舒适地存储或打印多行文本。即使你可以使用“here”文档中的变量。下面是一个简单的语法,仔细检查<<和标识符之间不能有空格。

标识符可能是裸字或一些引用的文本,如我们在下面使用EOF。如果引用标识符,您使用的报价类型决定了在这个文档中处理文本,就像常规引用一样。无引号的标识符类似双引号。

#!/usr/bin/perl

$a = 10;
$var = <<"EOF";
This is the syntax for here document and it will continue
until it encounters a EOF in the first line.
This is case of double quote so variable value will be 
interpolated. For example value of a = $a
EOF
print "$var
";

$var = <<"EOF";
This is case of single quote so variable value will not be 
interpolated. For example value of a = $a
EOF
print "$var
";

输出结果如下 -

This is the syntax for here document and it will continue
until it encounters a EOF in the first line.
This is case of double quote so variable value will be
interpolated. For example value of a = 10

This is case of single quote so variable value will be
interpolated. For example value of a = $a

逃避角色

Perl使用反斜杠()字符来转义可能会干扰我们的代码的任何类型的字符。让我们举一个例子,我们要打印双引号和$ sign -

#!/usr/bin/perl

$result = "This is "number"";
print "$result
";
print "$result
";

输出结果如下 -

This is "number"
$result

Perl标识符

Perl标识符是用于标识变量,函数,类,模块或其他对象的名称。Perl变量名以$,@或%开头,后跟零个或多个字母,下划线和数字(0到9)。

Perl不允许使用标识符中的@,$和%等标点符号。Perl是一个区分大小写的编程语言。因此,人力人力是Perl中两个不同的标识符。

Perl - 数据类型

Perl是一种松散类型的语言,在程序中使用时不需要为数据指定一个类型。Perl解释器将根据数据本身的上下文选择类型。

Perl有三种基本数据类型:标量,标量数组和标量散列,也称为关联数组。这是有关这些数据类型的一些细节。

没有 类型和说明
1 标量

标量是简单的变量。他们之前是一个美元符号($)。标量是数字,字符string或引用。一个参考实际上是一个变量的地址,我们将在以后的章节中看到。

2 数组

数组是使用数字索引访问的标量的有序列表,以0开头。它们之前带有“at”符号(@)。

3 哈希

哈希是使用键作为下标访问的无序的键/值对集合。前面加上百分号(%)。

数字文字

Perl将所有数字内部存储为有符号整数或双精度浮点值。数字文字以下列浮点或整数格式指定:

类型
int 1234
负整数 -100
浮点 2000年
科学计数法 16.12E14
十六进制 0xffff
八达通 0577

字符string文字

字符string是字符序列。它们通常是由单引号(")或双引号分隔的字母数字值,它们的工作方式与UNIX shell引号一样,您可以使用单引号和双引号。

双引号字符string文字允许变量插值,单引号字符string不是。当它们以反斜杠进行时,有某些字符,具有特殊含义,并且用于表示像换行符( n)或标签( t)。

您可以将换行符或任何以下Escape序列直接插入双引号字符string中 -

逃生顺序 含义
反斜杠
" 单引号
双引号
一个 警戒或响铃
b 退格
F 表格馈送
n 新队
r 回车返回
t 水平标签
v 垂直标签
0nn 创建八进制格式的数字
xnn 创建Hexideciamal格式的数字
cX 控制字符,x可以是任何字符
u 强制下一个字符大写
l 强制下一个字符为小写
U 将所有以下字符强制为大写
L 强制所有以下字符小写
Q 反斜杠所有以下非字母数字字符
E 结束 U, L或 Q

让我们再来看一下字符string的行为与单引号和双引号。这里我们将使用上表中提到的字符string转义,并使用标量变量来分配字符string值。

#!/usr/bin/perl

# This is case of interpolation.
$str = "Welcome to 
tutorialspoint.com!";
print "$str
";

# This is case of non-interpolation.
$str = "Welcome to 
tutorialspoint.com!";
print "$str
";

# Only W will become upper case.
$str = "uwelcome to tutorialspoint.com!";
print "$str
";

# Whole line will become capital.
$str = "UWelcome to tutorialspoint.com!";
print "$str
";

# A portion of line will become capital.
$str = "Welcome to UtutorialspointE.com!"; 
print "$str
";

# Backsalash non alpha-numeric including spaces.
$str = "QWelcome to tutorialspoint"s family";
print "$str
";

输出结果如下 -

Welcome to
tutorialspoint.com!
Welcome to 
tutorialspoint.com!
Welcome to tutorialspoint.com!
WELCOME TO TUTORIALSPOINT.COM!
Welcome to TUTORIALSPOINT.com!
Welcome to tutorialspoint"s family

Perl - 变量

变量是用于存储值的预留内存位置。这意味着当您创建一个变量时,您可以在内存中保留一些空间。

基于变量的数据类型,解释器分配内存并决定可以存储在保留的存储器中的内容。因此,通过为变量分配不同的数据类型,可以在这些变量中存储整数,小数或字符string。

我们了解到,Perl有以下三种基本数据类型 -

因此,我们将在Perl中使用三种类型的变量。标量变量将通过一个美元符号($)之前和它可以存储一个数字,字符string,或参考。一个数组变量将通过符号@前面,它会存储有序标量的列表。最后,哈希变量将以符号%前面,并将用于存储键/值对的集合。

Perl将每个变量类型维护在单独的命名空间中。所以你可以不用担心冲突,对标量变量,数组或散列使用相同的名称。这意味着$ foo和@foo是两个不同的变量。

创建变量

不必明确声明Perl变量来保留内存空间。当您向变量分配值时,会自动发出声明。等号(=)用于为变量赋值。

请注意,如果在我们的程序中使用strict语句,那么在使用它之前必须声明一个变量

=运算符左侧的操作数是变量的名称,而运算符右边的操作数是存储在变量中的值。例如 -

$age = 25;             # An integer assignment
$name = "John Paul";   # A string 
$salary = 1445.50;     # A floating point

这里25,“约翰保罗”和1445.50分别是分配给$ age$ name$ salary变量的值。很快我们将看到我们如何为数组和散列赋值。

标量变量

标量是单个数据单位。该数据可能是整数,浮点数,字符,字符string,段落或整个网页。简单地说这可能是什么,但只是一件事。

以下是使用标量变量的简单示例 -

#!/usr/bin/perl

$age = 25;             # An integer assignment
$name = "John Paul";   # A string 
$salary = 1445.50;     # A floating point

print "Age = $age
";
print "Name = $name
";
print "Salary = $salary
";

输出结果如下 -

Age = 25
Name = John Paul
Salary = 1445.5

数组变量

数组是存储标量值的有序列表的变量。数组变量前面加上“at”(@)符号。要引用数组的单个元素,您将使用带有变量名称的美元符号($),后跟元素的索引在方括号中。

以下是使用数组变量的简单示例 -

#!/usr/bin/perl

@ages = (25, 30, 40);             
@names = ("John Paul", "Lisa", "Kumar");

print "$ages[0] = $ages[0]
";
print "$ages[1] = $ages[1]
";
print "$ages[2] = $ages[2]
";
print "$names[0] = $names[0]
";
print "$names[1] = $names[1]
";
print "$names[2] = $names[2]
";

在这里,我们在$号之前使用转义符号()打印它。其他Perl将会将其理解为一个变量,并将其打印出来。执行时,将产生以下结果 -

$ages[0] = 25
$ages[1] = 30
$ages[2] = 40
$names[0] = John Paul
$names[1] = Lisa
$names[2] = Kumar

散列变量

散列是一组键/值对。哈希变量前面加上百分号(%)。要引用哈希的单个元素,您将使用哈希变量名称后跟“大写”括号中的值相关联的“键”。

以下是使用哈希变量的简单示例 -

#!/usr/bin/perl

%data = ("John Paul", 45, "Lisa", 30, "Kumar", 40);

print "$data{"John Paul"} = $data{"John Paul"}
";
print "$data{"Lisa"} = $data{"Lisa"}
";
print "$data{"Kumar"} = $data{"Kumar"}
";

输出结果如下 -

$data{"John Paul"} = 45
$data{"Lisa"} = 30
$data{"Kumar"} = 40

可变上下文

Perl根据上下文不同地对待相同的变量,即使用变量的情况。我们来看下面的例子 -

#!/usr/bin/perl

@names = ("John Paul", "Lisa", "Kumar");

@copy = @names;
$size = @names;

print "Given names are : @copy
";
print "Number of names are : $size
";

输出结果如下 -

Given names are : John Paul Lisa Kumar
Number of names are : 3

这里@names是一个数组,已被用在两个不同的上下文中。首先我们将它复制到任何其他数组,即列表中,所以它返回所有的元素,假设上下文是列表上下文。接下来,我们使用相同的数组,并尝试将此数组存储在标量中,因此在这种情况下,它只返回该数组中的元素数,假设上下文是标量上下文。下表列出了各种情况 -

没有 上下文说明
1 标量

赋值到标量变量可以在标量上下文中评估右侧。

2 列表

对数组或哈希的赋值将在列表上下文中对右侧进行评估。

3 boolean

布尔上下文只是表达式被评估以查看它是真还是假的任何地方。

4 空虚

这个上下文不仅不关心返回值是什么,它甚至不需要返回值。

5 插语

这个上下文只发生在引号内,或者像引号一样工作。

Perl - 标量

标量是单个数据单位。该数据可能是整数,浮点数,字符,字符string,段落或整个网页。

以下是使用标量变量的简单示例 -

#!/usr/bin/perl

$age = 25;             # An integer assignment
$name = "John Paul";   # A string 
$salary = 1445.50;     # A floating point

print "Age = $age
";
print "Name = $name
";
print "Salary = $salary
";

输出结果如下 -

Age = 25
Name = John Paul
Salary = 1445.5

数字标尺

标量通常是数字或字符string。以下示例演示了各种类型的数字标量的使用 -

#!/usr/bin/perl

$integer = 200;
$negative = -300;
$floating = 200.340;
$bigfloat = -1.2E-23;

# 377 octal, same as 255 decimal
$octal = 0377;

# FF hex, also 255 decimal
$hexa = 0xff;

print "integer = $integer
";
print "negative = $negative
";
print "floating = $floating
";
print "bigfloat = $bigfloat
";
print "octal = $octal
";
print "hexa = $hexa
";

输出结果如下 -

integer = 200
negative = -300
floating = 200.34
bigfloat = -1.2e-23
octal = 255
hexa = 255

字符string标量

以下示例演示了各种类型的字符string标量的用法。注意单引号和双引号之间的区别 -

#!/usr/bin/perl

$var = "This is string scalar!";
$quote = "I m inside single quote - $var";
$double = "This is inside single quote - $var";

$escape = "This example of escape -	Hello, World!";

print "var = $var
";
print "quote = $quote
";
print "double = $double
";
print "escape = $escape
";

输出结果如下 -

var = This is string scalar!
quote = I m inside single quote - $var                                                       
double = This is inside single quote - This is string scalar!                                
escape = This example of escape -       Hello, World

标量运算

您将在单独的章节中看到Perl中各种运算符的详细信息,但在这里我们将列出几个数字和字符string操作。

#!/usr/bin/perl

$str = "hello" . "world";       # Concatenates strings.
$num = 5 + 10;                  # adds two numbers.
$mul = 4 * 5;                   # multiplies two numbers.
$mix = $str . $num;             # concatenates string and number.

print "str = $str
";
print "num = $num
";
print "mix = $mix
";

输出结果如下 -

str = helloworld
num = 15
mix = helloworld15

多线string

如果要在程序中引入多行字符string,可以使用标准单引号,如下所示:

#!/usr/bin/perl

$string = "This is
a multiline
string";

print "$string
";

输出结果如下 -

This is
a multiline
string

您可以使用“here”文档语法存储或打印多行如下 -

#!/usr/bin/perl

print <<EOF;
This is
a multiline
string
EOF

这也将产生相同的结果 -

This is
a multiline
string

V字符string

形式为v1.20.300.4000的文字被解析为由具有指定序数的字符组成的字符string。这种形式被称为v字符string。

v字符string提供了替代和更可读的方式来构造字符string,而不是使用稍微较不易读的插值形式“ x {1} x {14} x {12c} x {fa0}”。

它们是以av开头的任何文字,后跟一个或多个点分隔元素。例如 -

#!/usr/bin/perl

$smile  = v9786;
$foo    = v102.111.111;
$martin = v77.97.114.116.105.110; 

print "smile = $smile
";
print "foo = $foo
";
print "martin = $martin
";

这也将产生相同的结果 -

smile = 
foo = foo
martin = Martin
Wide character in print at main.pl line 7. 

特别文字

到目前为止,你必须有一个关于字符string标量及其连接和插值操作的感觉。所以让我告诉你三个特殊的文字__FILE__,__LINE__和__PACKAGE__,代表当前的文件名,行号和程序包的名称。

它们可能仅用作单独的令牌,不会被内插到字符string中。检查下面的例子 -

#!/usr/bin/perl

print "File name ". __FILE__ . "
";
print "Line Number " . __LINE__ ."
";
print "Package " . __PACKAGE__ ."
";

# they can not be interpolated
print "__FILE__ __LINE__ __PACKAGE__
";

输出结果如下 -

File name hello.pl
Line Number 4
Package main
__FILE__ __LINE__ __PACKAGE__

Perl - 数组

数组是存储标量值的有序列表的变量。数组变量前面加上“at”(@)符号。要引用数组的单个元素,您将使用带有变量名称的美元符号($),后跟元素的索引在方括号中。

以下是使用数组变量的简单示例 -

#!/usr/bin/perl

@ages = (25, 30, 40);             
@names = ("John Paul", "Lisa", "Kumar");

print "$ages[0] = $ages[0]
";
print "$ages[1] = $ages[1]
";
print "$ages[2] = $ages[2]
";
print "$names[0] = $names[0]
";
print "$names[1] = $names[1]
";
print "$names[2] = $names[2]
";

这里我们在$号之前使用了转义符号()来打印它。其他Perl将会将其理解为一个变量,并将其打印出来。执行时,将产生以下结果 -

$ages[0] = 25
$ages[1] = 30
$ages[2] = 40
$names[0] = John Paul
$names[1] = Lisa
$names[2] = Kumar

在Perl中,List和Array术语通常被使用,就好像它们是可以互换的。但是列表是数据,而数组是变量。

数组创建

数组变量前缀为@符号,并使用括号或qw运算符填充。例如 -

@array = (1, 2, "Hello");
@array = qw/This is an array/;

第二行使用qw //运算符,它返回字符string列表,将分隔的字符string分隔为空格。在这个例子中,这导致一个四元素数组; 第一个元素是"this",last(4th)是"array"。这意味着您可以使用不同的行如下 -

@days = qw/Monday
Tuesday
...
Sunday/;

您还可以通过如下分别分配每个值来填充数组:

$array[0] = "Monday";
...
$array[6] = "Sunday";

访问数组元素

从数组访问各个元素时,您必须在变量前加一个美元符号($),然后在变量名称后的方括号内附加元素索引。例如 -

#!/usr/bin/perl

@days = qw/Mon Tue Wed Thu Fri Sat Sun/;

print "$days[0]
";
print "$days[1]
";
print "$days[2]
";
print "$days[6]
";
print "$days[-1]
";
print "$days[-7]
";

输出结果如下 -

Mon
Tue
Wed
Sun
Sun
Mon

数组索引从零开始,所以要访问第一个元素,你需要给出0作为索引。您还可以给出负数索引,在这种情况下,您从数组的结尾而不是开头选择元素。这意味着以下 -

print $days[-1]; # outputs Sun
print $days[-7]; # outputs Mon

顺序数组

Perl提供了序列号和字母的快捷方式。例如,当计数到100时,而不是打印出每个元素,我们可以执行以下操作:

#!/usr/bin/perl

@var_10 = (1..10);
@var_20 = (10..20);
@var_abc = (a..z);

print "@var_10
";   # Prints number from 1 to 10
print "@var_20
";   # Prints number from 10 to 20
print "@var_abc
";  # Prints number from a to z

这里双点(..)被称为范围运算符输出结果如下 -

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

数组大小

可以使用数组上的标量上下文来确定数组的大小 - 返回的值将是数组中的元素数 -

@array = (1,2,3);
print "Size: ",scalar @array,"
";

返回的值将始终是数组的物理大小,而不是有效元素的数量。您可以演示这一点,使用此片段的标量@array和$#数组之间的区别如下 -

#!/uer/bin/perl

@array = (1,2,3);
$array[50] = 4;

$size = @array;
$max_index = $#array;

print "Size:  $size
";
print "Max Index: $max_index
";

输出结果如下 -

Size: 51
Max Index: 50

数组中只有四个元素包含信息,但数组是51个元素长,索引最高为50。

在数组中添加和删除元素

Perl提供了一些有用的功能来添加和删除数组中的元素。你可能有什么问题是什么功能?到目前为止,您已经使用打印功能打印各种值。类似地,存在可以用于各种其他功能的各种其他功能或称为子例程的某个时间。

没有 类型和说明
1 推送@ARRAY,LIST

将列表的值推送到数组的末尾。

2 pop @ARRAY

弹出并返回数组的最后一个值。

3 移动@ARRAY

将数组的第一个值关闭并返回,将数组缩短1并将所有数据向下移动。

4 取消移除@ARRAY,LIST

将列表放在数组的前面,并返回新数组中的元素数。

#!/usr/bin/perl

# create a simple array
@coins = ("Quarter","Dime","Nickel");
print "1. @coins  = @coins
";

# add one element at the end of the array
push(@coins, "Penny");
print "2. @coins  = @coins
";

# add one element at the beginning of the array
unshift(@coins, "Dollar");
print "3. @coins  = @coins
";

# remove one element from the last of the array.
pop(@coins);
print "4. @coins  = @coins
";

# remove one element from the beginning of the array.
shift(@coins);
print "5. @coins  = @coins
";

输出结果如下 -

1. @coins = Quarter Dime Nickel
2. @coins = Quarter Dime Nickel Penny
3. @coins = Dollar Quarter Dime Nickel Penny
4. @coins = Dollar Quarter Dime Nickel
5. @coins = Quarter Dime Nickel

切片数组元素

您还可以从数组中提取“切片”,即可以从数组中选择多个项目,以生成另一个数组。

#!/usr/bin/perl

@days = qw/Mon Tue Wed Thu Fri Sat Sun/;

@weekdays = @days[3,4,5];

print "@weekdays
";

输出结果如下 -

Thu Fri Sat

切片的规范必须有一个有效索引的列表,无论是正的还是负的,每个都用逗号分隔。为了速度,您还可以使用..范围运算符 -

#!/usr/bin/perl

@days = qw/Mon Tue Wed Thu Fri Sat Sun/;

@weekdays = @days[3..5];

print "@weekdays
";

输出结果如下 -

Thu Fri Sat

更换数组元素

现在我们再介绍一个名为splice()的函数,它具有以下语法 -

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

此功能将删除由OFFSET和LENGTH指定的@ARRAY元素,如果指定,则用LIST替换它们。最后,它返回从数组中删除的元素。以下是这个例子 -

#!/usr/bin/perl

@nums = (1..20);
print "Before - @nums
";

splice(@nums, 5, 5, 21..25); 
print "After - @nums
";

输出结果如下 -

Before - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
After - 1 2 3 4 5 21 22 23 24 25 11 12 13 14 15 16 17 18 19 20

这里,实际的替换开始于第六个数字,然后将五个元素从6替换为10,数字21,22,23,24和25。

将字符string转换为数组

我们来研究一个名为split()的函数,它具有以下语法 -

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

此函数将字符string分割成字符string数组,并返回它。如果指定了LIMIT,则最多分割到该数量的字段。如果忽略了PATTERN,则分割空白。以下是这个例子 -

#!/usr/bin/perl

# define Strings
$var_string = "Rain-Drops-On-Roses-And-Whiskers-On-Kittens";
$var_names = "Larry,David,Roger,Ken,Michael,Tom";

# transform above strings into arrays.
@string = split("-", $var_string);
@names  = split(",", $var_names);

print "$string[3]
";  # This will print Roses
print "$names[4]
";   # This will print Michael

输出结果如下 -

Roses
Michael

将数组转换为字符string

我们可以使用join()函数重新加入数组元素并形成一个长标量字符string。此函数具有以下语法 -

join EXPR, LIST

此函数将LIST的单独字符string连接到一个单独的字符string,其字段以EXPR的值分隔,并返回该字符string。以下是这个例子 -

#!/usr/bin/perl

# define Strings
$var_string = "Rain-Drops-On-Roses-And-Whiskers-On-Kittens";
$var_names = "Larry,David,Roger,Ken,Michael,Tom";

# transform above strings into arrays.
@string = split("-", $var_string);
@names  = split(",", $var_names);

$string1 = join( "-", @string );
$string2 = join( ",", @names );

print "$string1
";
print "$string2
";

输出结果如下 -

Rain-Drops-On-Roses-And-Whiskers-On-Kittens
Larry,David,Roger,Ken,Michael,Tom

排序数组

排序()函数对根据ASCII数字标准的数组中的每个元素。此函数具有以下语法 -

sort [ SUBROUTINE ] LIST

此函数对LIST进行排序并返回排序的数组值。如果指定了SUBROUTINE,则在排序元素时应用SUBTROUTINE内的指定逻辑。

#!/usr/bin/perl

# define an array
@foods = qw(pizza steak chicken burgers);
print "Before: @foods
";

# sort this array
@foods = sort(@foods);
print "After: @foods
";

输出结果如下 -

Before: pizza steak chicken burgers
After: burgers chicken pizza steak

请注意,排序是根据ASCII的数字值进行的。所以最好的选择是首先将数组的每个元素转换成小写字母,然后执行排序函数。

$ [特殊变量

到目前为止,您已经看到我们在程序中定义的简单变量,并使用它们来存储和打印标量和数组值。Perl提供了许多特殊变量,它们具有预定的含义。

我们有一个特殊的变量,写成$ [此特殊变量是包含所有数组的第一个索引的标量。因为Perl数组具有基于零的索引,所以$ [几乎总是为0。但是如果将$ [设置为1,那么所有的数组都将使用基于索引的索引。建议不要使用除零之外的任何其他索引。但是,让我们举一个例子来显示$ [variable-

#!/usr/bin/perl

# define an array
@foods = qw(pizza steak chicken burgers);
print "Foods: @foods
";

# Let"s reset first index of all the arrays.
$[ = 1;

print "Food at @foods[1]: $foods[1]
";
print "Food at @foods[2]: $foods[2]
";

输出结果如下 -

Foods: pizza steak chicken burgers
Food at @foods[1]: pizza
Food at @foods[2]: steak

合并数组

因为数组只是一个逗号分隔的值序列,所以可以将它们组合在一起,如下所示:

#!/usr/bin/perl

@numbers = (1,3,(4,5,6));

print "numbers = @numbers
";

输出结果如下 -

numbers = 1 3 4 5 6

嵌入式数组刚刚成为主数组的一部分,如下所示:

#!/usr/bin/perl

@odd = (1,3,5);
@even = (2, 4, 6);

@numbers = (@odd, @even);

print "numbers = @numbers
";

输出结果如下 -

numbers = 1 3 5 2 4 6

从列表中选择元素

列表符号与数组相同。您可以通过向列表中添加方括号并提供一个或多个索引来从数组中提取元素 -

#!/usr/bin/perl

$var = (5,4,3,2,1)[4];

print "value of var = $var
"

输出结果如下 -

value of var = 1

类似地,我们可以提取片段,虽然没有要求一个领先的@字符 -

#!/usr/bin/perl

@list = (5,4,3,2,1)[1..3];

print "Value of list = @list
";

输出结果如下 -

Value of list = 4 3 2

Perl - 哈希

散列是一组键/值对。哈希变量前面加上百分号(%)。要引用哈希的单个元素,您将使用前面加上“$”符号的哈希变量名称,后跟“大写”括号中与该值相关联的“键”。

以下是使用哈希变量的简单示例 -

#!/usr/bin/perl

%data = ("John Paul", 45, "Lisa", 30, "Kumar", 40);

print "$data{"John Paul"} = $data{"John Paul"}
";
print "$data{"Lisa"} = $data{"Lisa"}
";
print "$data{"Kumar"} = $data{"Kumar"}
";

输出结果如下 -

$data{"John Paul"} = 45
$data{"Lisa"} = 30
$data{"Kumar"} = 40

创建哈希

哈希是通过以下两种方式之一创建的。在第一种方法中,您可以逐个指定一个值到命名键,

$data{"John Paul"} = 45;
$data{"Lisa"} = 30;
$data{"Kumar"} = 40;

在第二种情况下,您使用列表,该列表通过从列表中取出单个对进行转换:该对的第一个元素用作键,第二个元素作为值。例如 -

%data = ("John Paul", 45, "Lisa", 30, "Kumar", 40);

为了清楚起见,您可以使用=>作为别名,以指示键/值对如下:

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);

这里是上述形式的一个变体,看看它,这里所有的键都有连字符( - ),而不需要报价 -

%data = (-JohnPaul => 45, -Lisa => 30, -Kumar => 40);

但是重要的是要注意,有一个单词,即没有空格键在这种形式的哈希形成中被使用,如果你以这种方式创建哈希,那么键只能使用连字符来访问,如下所示。

$val = %data{-JohnPaul}
$val = %data{-Lisa}

访问哈希元素

从散列访问单个元素时,您必须在变量前面加上一个美元符号($),然后将元素键附加在变量名称之后的大括号中。例如 -

#!/usr/bin/perl

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);

print "$data{"John Paul"}
";
print "$data{"Lisa"}
";
print "$data{"Kumar"}
";

输出结果如下 -

45
30
40

提取切片

您可以像从数组中提取切片一样提取哈希片。您将需要使用@ prefix为变量存储返回的值,因为它们将是一个值列表 -

#!/uer/bin/perl


%data = (-JohnPaul => 45, -Lisa => 30, -Kumar => 40);

@array = @data{-JohnPaul, -Lisa};

print "Array : @array
";

输出结果如下 -

Array : 45 30

提取密钥和值

您可以使用功能从哈希中获取所有密钥的列表,该函数具有以下语法 -

keys %HASH

此函数返回所有命名哈希的所有键的数组。以下是这个例子 -

#!/usr/bin/perl 

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);

@names = keys %data;

print "$names[0]
";
print "$names[1]
";
print "$names[2]
";

输出结果如下 -

Lisa
John Paul
Kumar

类似地,您可以使用values函数来获取所有值的列表。此函数具有以下语法 -

values %HASH

此函数返回由命名哈希值的所有值组成的常规数组。以下是这个例子 -

#!/usr/bin/perl 

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);

@ages = values %data;

print "$ages[0]
";
print "$ages[1]
";
print "$ages[2]
";

输出结果如下 -

30
45
40

检查存在

如果您尝试从不存在的哈希访问密钥/值对,则通常会获取未定义的值,并且如果您打开了警告,则会在运行时生成警告。您可以通过使用exists函数来解决这个问题,如果命名的键存在,则返回true,而不管它的值可能是什么 -

#!/usr/bin/perl

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);

if( exists($data{"Lisa"} ) ){
   print "Lisa is $data{"Lisa"} years old
";
}
else{
   print "I don"t know age of Lisa
";
}

在这里我们介绍了IF ... ELSE语句,我们将在另一章中研究。现在你只要假设if(condition)部分只有在给定的条件为真时执行,否则将执行part。所以当我们执行上面的程序,它会产生以下结果,因为这里给定的条件存在($ data {"Lisa"}返回true -

Lisa is 30 years old

获取哈希大小

您可以通过使用键或值上的标量上下文来获取大小(即,哈希中的元素数)。简单地说,首先你必须得到一个数组的键或值,然后你可以得到如下的数组的大小 -

#!/usr/bin/perl

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);

@keys = keys %data;
$size = @keys;
print "1 - Hash size:  is $size
";

@values = values %data;
$size = @values;
print "2 - Hash size:  is $size
";

输出结果如下 -

1 - Hash size: is 3
2 - Hash size: is 3

在哈希中添加和删除元素

使用简单的赋值运算符可以使用一行代码来添加一个新的键/值对。但是要从哈希中删除一个元素,您需要使用delete函数,如下例所示:

#!/usr/bin/perl

%data = ("John Paul" => 45, "Lisa" => 30, "Kumar" => 40);
@keys = keys %data;
$size = @keys;
print "1 - Hash size:  is $size
";

# adding an element to the hash;
$data{"Ali"} = 55;
@keys = keys %data;
$size = @keys;
print "2 - Hash size:  is $size
";

# delete the same element from the hash;
delete $data{"Ali"};
@keys = keys %data;
$size = @keys;
print "3 - Hash size:  is $size
";

输出结果如下 -

1 - Hash size: is 3
2 - Hash size: is 4
3 - Hash size: is 3

Perl条件语句 - IF ... ELSE

Perl条件语句有助于判断,这要求程序员指定要由程序评估或测试的一个或多个条件,以及如果条件被确定为真,则要执行的语句或语句,以及可选地,其他如果条件被确定为假,则执行的语句。

以下是在大多数编程语言中发现的典型判断结构的一般性 -

Perl中的判断声明

数字0,字符string“0”和“”,空列表()和undef 在布尔上下文中都为false,所有其他值都为true否定一个真正的价值或者返回特殊的假值。

Perl编程语言提供以下类型的条件语句。

没有 声明和说明
1。 if语句

一个if语句由一个布尔表达式,后跟一个或多个语句组成。

2。 if... else语句

一个if语句可以跟随一个可选的else语句

3。 如果... elsif ... else语句

一个if语句可以后跟可选的elsif语句,然后是可选的else语句

4。 除非声明

一个except语句由布尔表达式组成,后跟一个或多个语句。

5。 除非... else语句

一个except语句可以后跟一个可选的else语句

6。 除非... elsif..else声明

一个except语句可以后跟一个可选的elsif语句,然后是可选的else语句

7。 switch

使用最新版本的Perl,您可以使用switch语句。这允许将变量值与各种条件进行比较的简单方法。

的?:操作符

我们来看条件运算符?可以用来替换if else else语句。它具有以下一般形式 -

Exp1 ? Exp2 : Exp3;

其中Exp1,Exp2和Exp3是表达式。注意冒号的使用和位置。

a的价值?表达式如下所示:Exp1被评估。如果它是真的,那么Exp2被评估并成为整个的值?表达。如果Exp1为false,则对Exp3进行求值,其值将变为表达式的值。下面是一个使用这个运算符的简单示例 -

#!/usr/local/bin/perl
 
$name = "Ali";
$age = 10;

$status = ($age > 60 )? "A senior citizen" : "Not a senior citizen";

print "$name is  - $status
";

输出结果如下 -

Ali is - Not a senior citizen

Perl - 循环

当您需要执行一段代码多次时可能会出现这种情况。一般来说,语句依次执行:函数中的第一个语句先执行,后跟第二个语句,依此类推。

编程语言提供了允许更复杂的执行路径的各种控制结构。

循环语句允许我们多次执行一个语句或一组语句,以下是大多数编程语言中循环语句的一般形式 -

Perl中的循环体系结构

Perl编程语言提供以下类型的循环来处理循环需求。

没有 循环类型和说明
1。 while循环

在给定条件为真时,重复一个语句或一组语句。它在执行循环体之前测试状态。

2。 直到循环

重复一个语句或一组语句,直到给定的条件成为true。它在执行循环体之前测试状态。

3。 for循环

多次执行一系列语句,并缩写管理循环变量的代码。

4。 foreach循环

foreach循环遍历正常列表值,并将变量VAR依次设置为列表的每个元素。

5。 do... while循环

像while语句一样,除了它测试循环体结尾的条件

6。 嵌套循环

你可以使用一个或多个循环内的任何一个,而对于或do..while循环。

循环控制语句

循环控制语句从其正常顺序更改执行。当执行离开范围时,在该范围内创建的所有自动对象都将被销毁。

C支持以下控制语句。单击以下链接以查看其详细信息。

没有 控制声明和说明
1。 下一个声明

导致循环跳过其身体的剩余部分,并在重申之前立即重新测试其状态。

2。 最后一句话

终止循环语句并将执行转移到循环之后的语句。

3。 continute

继续BLOCK,它总是在条件即将被再次评估之前执行。

4。 重做声明

redo命令重新启动循环块,而不再评估条件。继续块(如果有)不执行。

5。 goto声明

Perl支持一个具有三种形式的goto命令:goto label,goto expr和goto&name。

无限循环

如果条件永远不会变为假,则循环变为无限循环。传统上,for循环用于此目的。因为不需要形成for循环的三个表达式,所以你可以通过将条件表达式设置为空来做出无限循环。

#!/usr/local/bin/perl
 
for( ; ; )
{
   printf "This loop will run forever.
";
}

您可以通过按Ctrl + C键终止上述无限循环。

当条件表达式不存在时,它被假定为真。您可能有一个初始化和增量表达式,但是作为一个程序员更常使用for(;;)结构来表示一个无限循环。

Perl - 运算符

什么是运算符?

可以使用表达式4 + 5等于9给出简单的答案这里4和5称为操作数,+被称为运算符。Perl语言支持许多运算符类型,但以下是重要和最常用的运算符列表:

让我们看看所有的操作符一个接一个。

Perl算术运算符

假设变量$ a持有10,变量$ b成立20,则Perl算术运算符如下:

显示示例

没有 操作符和说明
1。 +(加法)

在操作符的两边添加值

示例 - $ a + $ b将给予30

2。 - (减法)

从左手操作数减去右手操作数

示例 - $ a - $ b将给予-10

3。 *(乘法)

在运算符的任一侧乘以值

示例 - $ a * $ b将给出200

4。 /(司)

用右手操作数除左手操作数

示例 - $ b / $ a将给出2

5。 %(模量)

用右手操作数除数左手操作数并返回余数

示例 - $ b%$ a将给出0

6。 **(指数)

对运算符进行指数(幂)计算

例子 - $ a ** $ b将给予权力20

Perl平等运算符

这些也称为关系运算符。假设变量$ a持有10,变量$ b成立20,则允许检查以下数字等式运算符 -

显示示例

没有 操作符和说明
1。 ==(等于)

检查两个操作数的值是否相等,如果是,则条件成立。

示例 - ($ a == $ b)不正确。

2。 !=(不等于)

检查两个操作数的值是否相等,如果值不等于条件成立。

示例 - ($ a!= $ b)为true。

3。 <=>

检查两个操作数的值是否相等,并根据左参数是否小于等于或大于正确的参数返回-1,0或1。

示例 - ($ a <=> $ b)返回-1。

4 >(大于)

检查左操作数的值是否大于右操作数的值,如果是,则条件成为真。

示例 - ($ a> $ b)不正确。

5。 (少于)

检查左操作数的值是否小于右操作数的值,如果是,则条件成为真。

示例 - ($ a <$ b)为true。

6。 > =(大于或等于)

检查左操作数的值是否大于或等于右操作数的值,如果是,则条件成为真。

示例 - ($ a> = $ b)不正确。

7。 <=(小于或等于)

检查左操作数的值是否小于或等于右操作数的值,如果是,则条件成为真。

示例 - ($ a <= $ b)为true。

以下是股权经营者名单。假设变量$ a表示“abc”,变量$ b表示“xyz”,则可以检查以下字符string相等运算符 -

显示示例

没有 操作符和说明
1。 lt

如果左参数的字符string小于正确的参数,则返回true。

示例 - ($ a lt $ b)为true。

2。 gt;

如果左参数的字符string大于正确的参数,则返回true。

示例 - ($ a gt $ b)为false。

3。 le

如果左参数的字符string小于或等于正确的参数,则返回true。

示例 - ($ a le $ b)为true。

4。 ge

如果左参数的字符string大于或等于正确的参数,则返回true。

示例 - ($ a ge $ b)为false。

5。 等式

如果左参数的字符string等于正确的参数,则返回true。

示例 - ($ a eq $ b)为false。

6。 ne

如果左参数的字符string不等于正确的参数,则返回true。

示例 - ($ a ne $ b)为true。

7。 厘米

根据左参数是否小于等于或大于正确的参数,返回-1,0或1。

示例 - ($ a cmp $ b)为-1。

Perl作业运算符

假设变量$ a持有10,变量$ b保持20,那么下面是Perl中可用的赋值运算符及其用法 -

显示示例

没有 操作符和说明
1。 =

简单赋值运算符,将右侧操作数的值分配给左侧操作数

示例 - $ c = $ a + $ b将$ a + $ b的值分配给$ c

2。 + =

添加AND赋值运算符,将右操作数添加到左操作数,并将结果分配给左操作数

示例 - $ c + = $ a等效于$ c = $ c + $ a

3。 - =

减去AND赋值运算符,从左操作数中减去右操作数,并将结果分配给左操作数

示例 - $ c - = $ a等效于$ c = $ c - $ a

4。 * =

乘以AND赋值运算符,将右操作数与左操作数相乘,并将结果分配给左操作数

示例 - $ c * = $ a等效于$ c = $ c * $ a

5。 / =

除以AND赋值运算符,它将左操作数与右操作数分开,并将结果分配给左操作数

示例 - $ c / = $ a等效于$ c = $ c / $ a

6。 %=

模数和赋值运算符,它使用两个操作数,并将结果分配给左操作数

示例 - $ c%= $ a等效于$ c = $ c%a

7。 ** =

指数AND赋值运算符,对运算符进行指数(幂次)运算,并将值分配给左操作数

示例 - $ c ** = $ a等价于$ c = $ c ** $ a

Perl位运算符

按位运算符对位进行运算并执行逐位运算。假设$ a = 60; 和$ b = 13; 现在以二进制格式,它们将如下 -

$ a = 0011 1100

$ b = 0000 1101

-----------------

$ a&$ b = 0000 1100

$ a | $ b = 0011 1101

$ a ^ $ b = 0011 0001

$ a = 1100 0011

Perl语言支持以下Bitwise运算符,假设$ a = 60; $ b = 13

显示示例

没有 操作符和说明
1。

如果二进制AND运算符存在于两个操作数中,则二进制AND运算符将对结果复制一位。

示例 - ($ a&$ b)将给出12是0000 1100

2 |

二进制OR运算符如果存在于操作数中,则复制一位。

示例 - ($ a | $ b)将给出61是0011 1101

3。 ^

二进制XOR操作符复制该位,如果它设置在一个操作数中,而不是两者。

示例 - ($ a ^ $ b)将给出49,其为0011 0001

4。

二进制补码运算符是一元的,具有“翻转”位的效果。

由于一个带符号的二进制数,例子 - ($ a)将给出-61,其中的二进制补码为1100 0011。

5。 <<

二进制左移操作符。左操作数值左移由右操作数指定的位数。

示例 - $ a << 2将给出240是1111 0000

6。 >>

二进制右移操作符。左操作数值被右操作数指定的位移动。

示例 - $ a >> 2将给出15是0000 1111

Perl逻辑运算符

Perl语言支持以下逻辑运算符。假设变量$ a成立,变量$ b保持false,然后 -

显示示例

没有 操作符和说明
1。

称为逻辑AND运算符。如果两个操作数都为真,那么条件成为真。

示例 - ($ a和$ b)为false。

2。 &&

如果C型逻辑AND运算符存在于两个操作数中,则将对该结果进行复制。

示例 - ($ a && $ b)为false。

3。

称为逻辑或运算符。如果两个操作数中的任何一个都为非零,则条件变为真。

示例 - ($ a或$ b)为真。

4。 ||

如果存在于eather操作数中,C风格的逻辑或运算符复制一点。

示例 - ($ a || $ b)为true。

5。

称为逻辑非运算符。用于反转其操作数的逻辑状态。如果条件为真,则逻辑NOT运算符将为false。

示例 - not($ a和$ b)是true。

报价式运算符

Perl语言支持以下类似Quote的运算符。在下表中,{}表示您选择的任何一对分隔符。

显示示例

没有 操作符和说明
1。 q {}

用单引号括起一个字符string

示例 - q {abcd}给出"abcd"

2。 qq {}

用双引号括起一个字符string

示例 - qq {abcd}给出“abcd”

3。 qx {}

包含一个带有in-in的引号的字符string

示例 - qx {abcd}给出“abcd”

杂项经营者

Perl语言支持以下各种运算符。假设变量a保持10,变量b保持20,则 -

显示示例

没有 操作符和说明
1。

二进制运算符点(。)连接两个字符string。

示例 - 如果$ a =“abc”,$ b =“def”,则$ a。$ b将给出“abcdef”

2。 X

重复操作符x返回由左操作数组成的字符string,重复由右操作数指定的次数。

示例 - (" - "x 3)将给出---。

3。 .. ..

范围运算符..将从左值计数(从1)的值列表返回到正确的值

示例 - (2..5)将给出(2,3,4,5)

4。 ++

自动增量运算符将整数值增加1

示例 - $ a ++将给出11

5。 -

自动递减运算符将整数值减1

例子 - $ a--将给出9

6。 - >

箭头运算符主要用于从对象或类名称中取消引用方法或变量

示例 - $ obj - > $ a是从对象$ obj访问变量$ a的示例。

Perl操作符优先级

下表列出了从最高优先级到最低优先级的所有运算符。

显示示例

left	terms and list operators (leftward)
left	->
nonassoc	++ --
right	**
right	! ~  and unary + and -
left	=~ !~
left	* / % x
left	+ - .
left	<< >>
nonassoc	named unary operators
nonassoc	< > <= >= lt gt le ge
nonassoc	== != <=> eq ne cmp ~~
left	&
left	| ^
left	&&
left	|| //
nonassoc	..  ...
right	?:
right	= += -= *= etc.
left	, =>
nonassoc	list operators (rightward)
right	not
left	and
left	or xor

Perl - 日期和时间

本章将介绍如何处理和处理Perl中日期和时间的基本知识。

当前日期和时间

我们从localtime()函数开始, 如果没有参数,它返回当前日期和时间的值。以下是在列表上下文中使用本地时间函数返回的9元素列表-

sec,     # seconds of minutes from 0 to 61
min,     # minutes of hour from 0 to 59
hour,    # hours of day from 0 to 24
mday,    # day of month from 1 to 31
mon,     # month of year from 0 to 11
year,    # year since 1900
wday,    # days since sunday
yday,    # days since January 1st
isdst    # hours of daylight savings time

尝试以下示例打印由localtime()函数返回的不同元素 -

#!/usr/local/bin/perl
 
@months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
@days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
print "$mday $months[$mon] $days[$wday]
";

当执行上述代码时,输出结果如下-

16 Feb Sat

如果您将在标量上下文中使用localtime()函数,那么它将从系统中设置的当前时区返回日期和时间。尝试以下示例以全格式打印当前日期和时间 -

#!/usr/local/bin/perl
 
$datestring = localtime();
print "Local date and time $datestring
";

当执行上述代码时,输出结果如下-

Local date and time Sat Feb 16 06:50:45 2013

GMT时间

函数gmtime()的工作方式与localtime()函数类似,但是返回的值被本地化为标准格林威治时区。当在列表上下文中调用时,$ isdst是gmtime返回的最后一个值,始终为0. GMT中没有夏令时。

您应该注意到localtime()将返回运行脚本的计算机上的当前本地时间,gmtime()将返回通用格林威治标准时间GMT或UTC。

尝试以下示例打印当前日期和时间,但是以GMT刻度 -

#!/usr/local/bin/perl

$datestring = gmtime();
print "GMT date and time $datestring
";

当执行上述代码时,输出结果如下-

GMT date and time Sat Feb 16 13:50:45 2013

格式日期和时间

您可以使用localtime()函数获取9个元素的列表,稍后可以使用printf()函数根据您的要求格式化日期和时间,如下所示:

#!/usr/local/bin/perl
 
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();

printf("Time Format - HH:MM:SS
");
printf("%02d:%02d:%02d", $hour, $min, $sec);

当执行上述代码时,输出结果如下-

Time Format - HH:MM:SS
06:58:52

大时代

您可以使用time()函数来获取时代,即从一个给定的日期开始的,在Unix中的秒数是1970年1月1日。

#!/usr/local/bin/perl
 
$epoc = time();

print "Number of seconds since Jan 1, 1970 - $epoc
";

当执行上述代码时,输出结果如下-

Number of seconds since Jan 1, 1970 - 1361022130

您可以将给定的秒数转换为日期和时间字符string,如下所示:

#!/usr/local/bin/perl

$datestring = localtime();
print "Current date and time $datestring
";

$epoc = time();
$epoc = $epoc - 12 * 60 * 60;   # one day before of current date.

$datestring = localtime($epoc);
print "Yesterday"s date and time $datestring
";

当执行上述代码时,输出结果如下-

Current date and time Sat Feb 16 07:05:39 2013
Yesterday"s date and time Fri Feb 15 19:05:39 2013

POSIX函数strftime()

您可以使用POSIX函数strftime()在下表的帮助下格式化日期和时间。请注意,标有星号(*)的说明符与区域设置相关。

指定者 取而代之
%a 缩写工作日名称* Thu
%A 全日制名称* Thursday
%b 缩写月份名* Aug
%B 全月名* August
%c 日期和时间表示* Thu Aug 23 14:55:02 2001
%C 年除以100,并截断为整数(00-9920
%d 一个月的日子,零填充(01-31 23
%D shortMM/DD/YY日期,相当于%m/%d/%y 08/23/01
%e 一个月的一天,空间填充( 1-31 23
%F shortYYYY-MM-DD日期,相当于%Y-%m-%d 2001-08-23
%g 基于周的年份,最后两位数字(00-99 01
%g 基于周的一年 2001
%h 缩写月名*(同%b Aug
%H 24小时格式(00-23 14
%I 小时12小时格式(01-12 02
%j 一年中的(001-366 235
%m 月作为十进制数(01-12 08
%M 分钟(00-59 55
%n 新行字符(" "
%p AM或PM指定 PM
%r 12小时时钟* 02:55:02 pm
%R 24小时的HH:MM时间,相当于%H:%M 14:55
%S 第二(00-61 02
%t 水平标签字符(" "
%T ISO 8601时间格式(HH:MM:SS),相当于%H:%M:%S 14:55
%u ISO 8601工作日与星期一为11-7 4
%U 周数第一个星期日是第一周的第一天(00-53 33
%V ISO 8601周数(00-53 34
%w 工作日作为十进制数,星期日为00-6 4
%W 周号为第一个星期一为第一周(00-53 34
%x 日期代表* 08/23/01
%X 时间表示* 14:55:02
%y 年份,最后两位数字(00-99 01
%Y 2001
%z

ISO 8601偏离UTC在时区(1分= 1,1小时= 100)

如果时区无法终止,则无字符

+100
%Z

时区名称或缩写*

如果时区无法终止,则无字符

CDT
%% 一个%标志 %

我们来看下面的例子来了解用法 -

#!/usr/local/bin/perl
use POSIX qw(strftime);

$datestring = strftime "%a %b %e %H:%M:%S %Y", localtime;
printf("date and time - $datestring
");

# or for GMT formatted appropriately for your locale:
$datestring = strftime "%a %b %e %H:%M:%S %Y", gmtime;
printf("date and time - $datestring
");

当执行上述代码时,输出结果如下-

date and time - Sat Feb 16 07:10:23 2013
date and time - Sat Feb 16 14:10:23 2013

Perl - 子程序

Perl子例程或函数是一组一起执行任务的语句。您可以将代码分成单独的子例程。如何在不同的子程序之间划分代码取决于你,但是在逻辑上,分区通常是每个函数执行一个特定的任务。

Perl可以互换使用术语子程序,方法和功能。

定义并调用子程序

Perl编程语言中子例程定义的一般形式如下 -

sub subroutine_name{
   body of the subroutine
}

调用Perl子程序的典型方法如下:

subroutine_name( list of arguments );

在5.0之前的Perl版本中,调用子例程的语法略有不同,如下所示。这仍然适用于Perl的最新版本,但不推荐它,因为它绕过子例程prototype。

&subroutine_name( list of arguments );

我们来看看下面的例子,它定义了一个简单的函数,然后调用它。因为Perl在执行程序之前编译程序,所以在你声明子程序的时候并不重要。

#!/usr/bin/perl

# Function definition
sub Hello{
   print "Hello, World!
";
}

# Function call
Hello();

当执行上述程序时,输出结果如下-

Hello, World!

将参数传递给子程序

您可以将各种参数传递给一个子程序,就像使用其他编程语言一样,它们可以使用特殊数组@_在函数内部进行读取。因此,函数的第一个参数是$ _ [0],第二个参数在$ _ [1]中,依此类推。

您可以将数组和散列作为任何标量的参数传递,但传递多个数组或散列通常会导致它们丢失其独立的标识。所以我们将使用引用(在下一章中解释)传递任何数组或散列。

让我们尝试以下示例,其中列出了数字,然后打印出他们的平均值 -

#!/usr/bin/perl

# Function definition
sub Average{
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_){
      $sum += $item;
   }
   $average = $sum / $n;

   print "Average for the given numbers : $average
";
}

# Function call
Average(10, 20, 30);

当执行上述程序时,输出结果如下-

Average for the given numbers : 20

将列表传递给子程序

因为@_变量是一个数组,它可以用于向子例程提供列表。然而,由于Perl接受和解析列表和数组的方式,可能难以从@_中提取单个元素。如果您必须与其他标量参数一起传递列表,则将列表作为最后一个参数,如下所示:

#!/usr/bin/perl

# Function definition
sub PrintList{
   my @list = @_;
   print "Given list is @list
";
}
$a = 10;
@b = (1, 2, 3, 4);

# Function call with list parameter
PrintList($a, @b);

当执行上述程序时,输出结果如下-

Given list is 10 1 2 3 4

将哈希传递给子程序

当您向接受列表的子例程或运算符提供哈希时,哈希将自动转换为键/值对列表。例如 -

#!/usr/bin/perl

# Function definition
sub PrintHash{
   my (%hash) = @_;

   foreach my $key ( keys %hash ){
      my $value = $hash{$key};
      print "$key : $value
";
   }
}
%hash = ("name" => "Tom", "age" => 19);

# Function call with hash parameter
PrintHash(%hash);

当执行上述程序时,输出结果如下-

name : Tom
age : 19

从子程序返回值

你可以从子程序返回一个值,就像你在其他编程语言中一样。如果您没有从子程序返回值,则子程序中最后执行的任何计算都将自动返回值。

您可以像任何标量一样从子例程返回数组和散列,但返回多个数组或散列通常会导致它们丢失其独立的标识。所以我们将使用引用(在下一章中说明)从函数返回任何数组或散列。

让我们试试下面的例子,其中列出了数字,然后返回他们的平均值 -

#!/usr/bin/perl

# Function definition
sub Average{
   # get total number of arguments passed.
   $n = scalar(@_);
   $sum = 0;

   foreach $item (@_){
      $sum += $item;
   }
   $average = $sum / $n;

   return $average;
}

# Function call
$num = Average(10, 20, 30);
print "Average for the given numbers : $num
";

当执行上述程序时,输出结果如下-

Average for the given numbers : 20

子程序中的私有变量

默认情况下,Perl中的所有变量都是全局变量,这意味着可以从程序中的任何位置访问它们。但是您可以随时使用我的操作符创建名为词法变量的私有变量

我的操作者地限制在其中它可以被用来访问和一个特定的代码区域的变量。在该区域之外,该变量不能被使用或访问。这个地区被称为它的范围。词汇范围通常是一组代码,其周围有一组括号,例如定义子例程的主体或标记if,while,for foreacheval语句的代码块的代码块

以下是一个示例,显示如何使用我的运算符定义单个或多个私有变量-

sub somefunc {
   my $variable; # $variable is invisible outside somefunc()
   my ($another, @an_array, %a_hash); # declaring many variables at once
}

我们来看下面的例子来区分全局和私有变量 -

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

# Function definition
sub PrintHello{
   # Private variable for PrintHello function
   my $string;
   $string = "Hello, Perl!";
   print "Inside the function $string
";
}
# Function call
PrintHello();
print "Outside the function $string
";

当执行上述程序时,输出结果如下-

Inside the function Hello, Perl!
Outside the function Hello, World!

通过本地()

当地主要是用来当一个变量的当前值必须是调用的子程序可见。一个局部的只是给全局(意思是包)变量的临时值。这被称为动态范围词汇范围由我完成,其工作更像C的自动声明。

如果给本地提供了多个变量或表达式,则必须将其放在括号中。此操作符通过将隐藏堆栈中的参数列表中的这些变量的当前值保存起来,并在退出块,子例程或eval时将其还原。

我们来看下面的例子来区分全局和局部变量 -

#!/usr/bin/perl

# Global variable
$string = "Hello, World!";

sub PrintHello{
   # Private variable for PrintHello function
   local $string;
   $string = "Hello, Perl!";
   PrintMe();
   print "Inside the function PrintHello $string
";
}
sub PrintMe{
   print "Inside the function PrintMe $string
";
}

# Function call
PrintHello();
print "Outside the function $string
";

当执行上述程序时,输出结果如下-

Inside the function PrintMe Hello, Perl!
Inside the function PrintHello Hello, Perl!
Outside the function Hello, World!

状态变量通过state()

还有一种类型的词法变量,它们类似于私有变量,但它们保持状态,并且在多次调用子程序时不会被重新初始化。这些变量使用状态运算符定义,可从Perl 5.9.4开始。

我们来看下面的例子来说明如何使用状态变量 -

#!/usr/bin/perl

use feature "state";

sub PrintCount{
   state $count = 0; # initial value

   print "Value of counter is $count
";
   $count++;
}

for (1..5){
   PrintCount();
}

当执行上述程序时,输出结果如下-

Value of counter is 0
Value of counter is 1
Value of counter is 2
Value of counter is 3
Value of counter is 4

在Perl 5.10之前,你必须这样写 -

#!/usr/bin/perl

{
   my $count = 0; # initial value

   sub PrintCount {
      print "Value of counter is $count
";
      $count++;
   }
}

for (1..5){
   PrintCount();
}

子程序调用上下文

子例程或语句的上下文被定义为期望的返回值的类型。这允许您使用单个函数根据用户期望接收的内容返回不同的值。例如,当在标量上下文中调用时,以下localtime()返回一个字符string,但是当它在列表上下文中调用时返回一个列表。

my $datestring = localtime( time );

在此示例中,$ timestr的值现在是由当前日期和时间组成的字符string,例如Thu Nov 30 15:21:33 2000.相反 -

($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);

现在,各个变量包含localtime()子例程返回的相应值。

Perl - 参考

Perl引用是一个标量数据类型,它保存可以是标量,数组或散列值的另一个值的位置。由于其标量性质,可以在任何地方使用引用,可以使用标量。

您可以构造包含对其他列表的引用的列表,其中可以包含对散列的引用,等等。这是嵌入式数据结构在Perl中的创建方式。

创建参考

为任何变量,子例程或值创建引用是很容易的,前缀为反斜杠,如下所示:

$scalarref = $foo;
$arrayref  = @ARGV;
$hashref   = \%ENV;
$coderef   = &handler;
$globref   = *foo;

您不能使用反斜杠运算符在I / O句柄(filehandle或dirhandle)上创建引用,但是可以使用方括号如下创建对匿名数组的引用:

 $arrayref = [1, 2, ["a", "b", "c"]];

类似的方式,您可以使用如下的大括号创建对匿名哈希的引用:

$hashref = {
   "Adam"  => "Eve",
   "Clyde" => "Bonnie",
};

可以通过使用没有子名的子句来创建对匿名子例程的引用,如下所示:

$coderef = sub { print "Boink!
" };

取消引用

取消引用将值从参考点返回到位置。要引用引用,只需使用$,@或%作为引用变量的前缀,具体取决于引用是指向标量,数组还是散列。以下是解释概念的例子 -

#!/usr/bin/perl

$var = 10;

# Now $r has reference to $var scalar.
$r = $var;

# Print value available at the location stored in $r.
print "Value of $var is : ", $$r, "
";

@var = (1, 2, 3);
# Now $r has reference to @var array.
$r = @var;
# Print values available at the location stored in $r.
print "Value of @var is : ",  @$r, "
";

%var = ("key1" => 10, "key2" => 20);
# Now $r has reference to %var hash.
$r = \%var;
# Print values available at the location stored in $r.
print "Value of %var is : ", %$r, "
";

当执行上述程序时,输出结果如下-

Value of 10 is : 10
Value of 1 2 3 is : 123
Value of %var is : key220key110

如果您不确定变量类型,那么它很容易使用ref来知道它的类型,如果参数是一个引用,返回以下字符string之一。否则返回false -

SCALAR
ARRAY
HASH
CODE
GLOB
REF

我们来试试下面的例子 -

#!/usr/bin/perl

$var = 10;
$r = $var;
print "Reference type in r : ", ref($r), "
";

@var = (1, 2, 3);
$r = @var;
print "Reference type in r : ", ref($r), "
";

%var = ("key1" => 10, "key2" => 20);
$r = \%var;
print "Reference type in r : ", ref($r), "
";

当执行上述程序时,输出结果如下-

Reference type in r : SCALAR
Reference type in r : ARRAY
Reference type in r : HASH

循环引用

当两个引用包含彼此的引用时,会发生循环引用。创建引用时必须小心,否则循环引用可能导致内存泄漏。以下是一个例子 -

#!/usr/bin/perl

 my $foo = 100;
 $foo = $foo;
 
 print "Value of foo is : ", $$foo, "
";

当执行上述程序时,输出结果如下-

Value of foo is : REF(0x9aae38)

参考函数

如果您需要创建一个信号处理程序,以便您可以通过使用前面的函数名称来产生对函数的引用,并使用&符号引用引用引用变量,那么可能会发生这种情况。以下是一个例子 -

#!/usr/bin/perl

# Function definition
sub PrintHash{
   my (%hash) = @_;
   
   foreach $item (%hash){
      print "Item : $item
";
   }
}
%hash = ("name" => "Tom", "age" => 19);

# Create a reference to above function.
$cref = &PrintHash;

# Function call using reference.
&$cref(%hash);

当执行上述程序时,输出结果如下-

Item : name
Item : Tom
Item : age
Item : 19

Perl格式

Perl使用一个名为“format”的写入模板来输出报告。要使用Perl的格式功能,您必须首先定义格式,然后可以使用该格式写入格式化的数据。

定义格式

以下是定义Perl格式的语法 -

format FormatName =
fieldline
value_one, value_two, value_three
fieldline
value_one, value_two
.

这里FormatName表示格式的名称。的Fieldline是具体的方式,数据应该被格式化。值行表示将输入到字段行的值。您以单一期限结束格式。

下一个字段可以包含任何文本或字段持有者。现场持有人将在稍后的日期放置在那里的数据空间。现场持有人有格式 -

@<<<<

该字段保留为左对齐,字段空间为5.您必须对@符号和<符号进行计数才能知道字段中的空格数。其他范围持有人包括 -

@>>>> right-justified
@|||| centered
@####.## numeric field holder
@* multiline field holder

一个示例格式是 -

format EMPLOYEE =
===================================
@<<<<<<<<<<<<<<<<<<<<<< @<< 
$name $age
@#####.##
$salary
===================================
.

在这个例子中,$ name将在22个字符空格内写成左对齐,之后这个年龄将被写入两个空格。

使用格式

为了调用此格式声明,我们将使用write关键字 -

write EMPLOYEE;

问题是,格式名称通常是打开的文件句柄的名称,写入语句会将输出发送到该文件句柄。我们希望将数据发送到STDOUT,我们必须将EMPLOYEE与STDOUT文件句柄相关联。首先,我们必须使用select()函数确保STDOUT是我们选择的文件句柄。

select(STDOUT);

然后,我们将使用STDOUT将EMPLOYEE与STDOUT相关联,使用特殊变量$或$ FORMAT_NAME设置新的格式名称,如下所示:

$~ = "EMPLOYEE";

当我们现在做一个write()时,数据将被发送到STDOUT。记住:如果你要用任何其他文件句柄编写报告,而不是STDOUT,那么你可以使用select()函数来选择该文件句柄,其余的逻辑将保持不变。

我们来看下面的例子。这里我们有硬编码值只是为了显示用法。在实际使用中,您将从文件或数据库读取值以生成实际报告,您可能需要再次将最终报告写入文件。

#!/usr/bin/perl

format EMPLOYEE =
===================================
@<<<<<<<<<<<<<<<<<<<<<< @<< 
$name $age
@#####.##
$salary
===================================
.

select(STDOUT);
$~ = EMPLOYEE;

@n = ("Ali", "Raza", "Jaffer");
@a  = (20,30, 40);
@s = (2000.00, 2500.00, 4000.000);

$i = 0;
foreach (@n){
   $name = $_;
   $age = $a[$i];
   $salary = $s[$i++];
   write;
}

执行时,将产生以下结果 -

===================================
Ali                     20
  2000.00
===================================
===================================
Raza                    30
  2500.00
===================================
===================================
Jaffer                  40
  4000.00
===================================

定义报表标题

一切看起来都不错 但您有兴趣在报告中添加标题。此标题将打印在每页的顶部。这样做很简单。除了定义一个模板,您必须定义一个标题并将其分配给$ ^或$ FORMAT_TOP_NAME变量 -

#!/usr/bin/perl

format EMPLOYEE =
===================================
@<<<<<<<<<<<<<<<<<<<<<< @<< 
$name $age
@#####.##
$salary
===================================
.

format EMPLOYEE_TOP =
===================================
Name                    Age
===================================
.

select(STDOUT);
$~ = EMPLOYEE;
$^ = EMPLOYEE_TOP;

@n = ("Ali", "Raza", "Jaffer");
@a  = (20,30, 40);
@s = (2000.00, 2500.00, 4000.000);

$i = 0;
foreach (@n){
   $name = $_;
   $age = $a[$i];
   $salary = $s[$i++];
   write;
}

现在你的报告会像 -

===================================
Name                    Age
===================================
===================================
Ali                     20
  2000.00
===================================
===================================
Raza                    30
  2500.00
===================================
===================================
Jaffer                  40
  4000.00
===================================

定义分页

如果您的报告正在使用多个页面,该怎么办?您有一个解决方案,只需使用$%或$ FORMAT_PAGE_NUMBER,以及标题如下所示:

format EMPLOYEE_TOP =
===================================
Name                    Age Page @<
                                 $%
===================================                               
.

现在您的输出将如下所示:

===================================
Name                    Age Page 1
===================================
===================================
Ali                     20
  2000.00
===================================
===================================
Raza                    30
  2500.00
===================================
===================================
Jaffer                  40
  4000.00
===================================

页面上的行数

您可以使用特殊变量$ =(或$ FORMAT_LINES_PER_PAGE)设置每页的行数,默认情况下$ = 60。

定义报表页脚

虽然$ ^或$ FORMAT_TOP_NAME包含当前标题格式的名称,但没有相应的机制来自动为页脚执行相同的操作。如果你有一个固定大小的页脚,你可以通过在每个write()之前检查变量$ - 或$ FORMAT_LINES_LEFT来获得页脚,并且如果需要,使用另外定义如下的格式打印页脚:

format EMPLOYEE_BOTTOM =
End of Page @<
            $%
.

有关与格式相关的一整套变量,请参考Perl特殊变量部分。

Perl - 文件I / O

处理文件的基本原理很简单:将文件句柄与外部实体(通常是文件)相关联,然后使用Perl中的各种运算符和函数来读取和更新存储在与文件句柄相关联的数据流中的数据。

文件句柄是一个命名的内部Perl结构,它将物理文件与名称相关联。所有文件句柄都具有读/写访问权限,因此您可以读取和更新与文件句柄相关联的任何文件或设备。但是,当您关联文件句柄时,可以指定打开文件句柄的模式。

三个基本文件句柄分别为STDINSTDOUTSTDERR,分别代表标准输入,标准输出和标准错误设备。

打开和关闭文件

以下两个函数有多种形式,可用于打开Perl中的任何新的或现有的文件。

open FILEHANDLE, EXPR
open FILEHANDLE

sysopen FILEHANDLE, FILENAME, MODE, PERMS
sysopen FILEHANDLE, FILENAME, MODE

这里FILEHANDLE是由open函数返回的文件句柄,EXPR是具有打开文件的文件名和模式的表达式。

开放功能

以下是以只读模式打开file.txt的语法这里小于<符号表示文件必须在只读模式下运行。

open(DATA, "<file.txt");

这里DATA是文件句柄,将用于读取文件。这是一个例子,它将打开一个文件,并将其屏幕上的内容打印出来。

#!/usr/bin/perl

open(DATA, "<file.txt") or die "Couldn"t open file file.txt, $!";

while(<DATA>){
   print "$_";
}

以下是在写入模式下打开file.txt的语法。这里小于>符号表示文件必须在写入模式下运行。

open(DATA, ">file.txt") or die "Couldn"t open file file.txt, $!";

此示例实际上在打开文件之前截断(清空)文件,这可能不是所需的效果。如果要打开文件进行阅读和写入,可以在>或<characters之前加一个加号。

例如,打开一个文件进行更新而不截断它 -

open(DATA, "+<file.txt"); or die "Couldn"t open file file.txt, $!";

要截断文件首先 -

open DATA, "+>file.txt" or die "Couldn"t open file file.txt, $!";

您可以以附加模式打开文件。在此模式下,写入点将设置为文件的末尾。

open(DATA,">>file.txt") || die "Couldn"t open file file.txt, $!";

一个double >>打开文件进行追加,将文件指针放在最后,以便您可以立即开始附加信息。但是,除非您在前面加一个加号,否则您无法读取它 -

open(DATA,"+>>file.txt") || die "Couldn"t open file file.txt, $!";

以下是表格,它给出了不同模式的可能值

没有 实体与定义
1。 <或r

只读访问

2。 >或w

创建,写入和截断

3。 >>或a

写,追加和创造

4。 + <或r +

阅读和写作

5。 +>或w +

阅读,写作,创作和截断

6。 + >>或a +

阅读,写入,追加和创建

Sysopen功能

的sysopen功能类似于主开功能,不同之处在于它使用系统的open()函数,利用提供给它作为系统函数的参数的参数-

例如,要打开一个文件用于更新,仿效+ <文件名从开放格式-

sysopen(DATA, "file.txt", O_RDWR);

或者在更新之前截断文件 -

sysopen(DATA, "file.txt", O_RDWR|O_TRUNC );

您可以使用O_CREAT创建一个新文件,O_WRONLY-以只写模式打开文件,并以O_RDONLY打开文件,以只读模式打开文件。

PERMS参数指定的文件权限指定的文件,如果它被创建。默认情况下需要0x666

以下是表格,它给出了MODE的可能值。

没有 实体与定义
1。 O_RDWR

读和写

2。 O_RDONLY

只读

3。 O_WRONLY

只写

4。 O_CREAT

创建文件

5。 O_APPEND

附加文件

6。 O_TRUNC

截断文件

7。 O_EXCL

停止,如果文件已经存在

8。 O_NONBLOCK

不阻止可用性

关闭功能

要关闭文件句柄,因此将文件句柄与相应文件取消关联,您可以使用close函数。这将刷新文件句柄的缓冲区并关闭系统的文件描述符。

close FILEHANDLE
close

如果没有指定FILEHANDLE,那么它将关闭当前选定的文件句柄。它只有在可以成功刷新缓冲区并关闭文件时才会返回true。

close(DATA) || die "Couldn"t close file properly";

阅读和写作文件

一旦你有一个开放的文件句柄,你需要能够读写信息。有多种不同的方式来读取和写入文件中的数据。

<FILEHANDL>运算符

从打开的文件句柄读取信息的主要方法是<FILEHANDLE>运算符。在标量上下文中,它从文件句柄返回一行。例如 -

#!/usr/bin/perl

print "What is your name?
";
$name = <STDIN>;
print "Hello $name
";

当您在列表上下文中使用<FILEHANDLE>操作符时,它将从指定的文件句柄返回一行行。例如,要将文件中的所有行导入数组 -

#!/usr/bin/perl

open(DATA,"<import.txt") or die "Can"t open data";
@lines = <DATA>;
close(DATA);

getc函数

getc函数从指定的FILEHANDLE返回单个字符,如果没有指定,则返回STDIN -

getc FILEHANDLE
getc

如果出现错误,或者文件句柄在文件的末尾,则会返回undef。

读功能

读取功能从缓冲的文件句柄中读取一个信息块:该函数用于从文件读取二进制数据。

read FILEHANDLE, SCALAR, LENGTH, OFFSET
read FILEHANDLE, SCALAR, LENGTH

读取的数据长度由LENGTH定义,如果没有指定OFFSET,数据将放在SCALAR的开头。否则数据放在SCALAR中的OFFSET字节之后。该函数返回成功读取的字节数,文件结尾为零,如果发生错误,则返回undef。

打印功能

对于从文件句柄读取信息的所有不同方法,写入信息的主要功能是打印功能。

print FILEHANDLE LIST
print LIST
print

打印功能将LIST的评估值打印到FILEHANDLE,或打印到当前输出文件句柄(默认为STDOUT)。例如 -

print "Hello World!
";

复制文件

这是一个例子,它打开一个现有的file1.txt文件,逐行读取并生成另一个文件file2.txt。

#!/usr/bin/perl

# Open file to read
open(DATA1, "<file1.txt");

# Open new file to write
open(DATA2, ">file2.txt");

# Copy data from one file to another.
while(<DATA1>)
{
   print DATA2 $_;
}
close( DATA1 );
close( DATA2 );

重命名文件

这是一个例子,它显示了如何将文件file1.txt重命名为file2.txt。假设文件在/ usr / test目录中可用。

#!/usr/bin/perl

rename ("/usr/test/file1.txt", "/usr/test/file2.txt" );

此函数重命名有两个参数,它只是重命名现有文件。

删除现有文件

这是一个例子,它显示了如何使用unlink函数删除file1.txt文件

#!/usr/bin/perl

unlink ("/usr/test/file1.txt");

定位在文件中

您可以使用告诉功能来了解文件的当前位置,并寻找功能来指定文件中的特定位置。

告诉功能

第一个要求是找到你在一个文件中的位置,你使用tell函数 -

tell FILEHANDLE
tell

如果指定,则返回文件指针的位置(以字节为单位),如果指定,则返回当前默认选择的文件句柄。

寻求功能

搜索功能将文件指针定位到文件中指定的字节数 -

seek FILEHANDLE, POSITION, WHENCE

该功能使用fseek系统功能,并且具有相对于三个不同点定位的能力:开始,结束和当前位置。您可以通过为WHENCE指定值来执行此操作。

零设置相对于文件开头的位置。例如,该行将文件指针设置为文件中的第256个字节。

seek DATA, 256, 0;

文件信息

您可以使用一系列统称为-X测试的测试运算符,在Perl中快速测试某些功能。例如,要对文件的各种权限执行快速测试,可以使用这样的脚本 -

#/usr/bin/perl

my $file = "/usr/test/file1.txt";
my (@description, $size);
if (-e $file)
{
   push @description, "binary" if (-B _);
   push @description, "a socket" if (-S _);
   push @description, "a text file" if (-T _);
   push @description, "a block special file" if (-b _);
   push @description, "a character special file" if (-c _);
   push @description, "a directory" if (-d _);
   push @description, "executable" if (-x _);
   push @description, (($size = -s _)) ? "$size bytes" : "empty";
   print "$file is ", join(", ",@description),"
";
}

以下是功能列表,您可以检查文件或目录 -

没有 操作符和定义
1。 -一个

脚本开始时间减去文件最后访问时间,以天为单位。

2。 -B

是二进制文件吗?

3。 -C

脚本开始时间减去文件最后一个inode更改时间,以天为单位。

3。 -M

脚本开始时间减去文件修改时间,以天为单位。

4。 -O

该文件是否由真实用户ID拥有?

5。 -R

该文件可以被真实的用户ID或真实组读取吗?

6。 -S

文件是套接字吗?

7。 -T

是文本文件吗?

8。 -W

该文件是由真实用户ID还是实际组写入?

9。 -X

该文件是否可由真实用户ID或实体组执行?

10。 -b

是一个特殊文件块?

11。 -C

这是一个字符特殊文件吗?

12。 -d

文件是目录吗?

13。 -e

文件是否存在?

14。 -F

是纯文件吗?

15。 -G

文件是否设置了setgid位?

16。 -k

文件是否有粘性位?

17。 -l

文件是一个符号链接吗?

18。 -o

文件是否由有效用户ID拥有?

19。 -p

文件是命名管道吗?

20。 -r

该文件可以被有效的用户或组ID读取吗?

21。 -s

返回文件的大小,零大小=空文件。

22。 -t

文件句柄是否由TTY(终端)打开?

23。 -u

该文件是否设置了setuid位?

24。 -w

该文件是否由有效用户或组ID写入?

25。 -X

该文件是否可由有效用户或组ID执行?

26。 -z

文件大小是否为零?

Perl - 目录

以下是用于播放目录的标准功能。

opendir DIRHANDLE, EXPR  # To open a directory
readdir DIRHANDLE        # To read a directory
rewinddir DIRHANDLE      # Positioning pointer to the begining
telldir DIRHANDLE        # Returns current position of the dir
seekdir DIRHANDLE, POS   # Pointing pointer to POS inside dir
closedir DIRHANDLE       # Closing a directory.

显示所有文件

有各种方法可以列出特定目录中可用的所有文件。首先,我们使用简单的方式来获取并列出所有使用glob运算符的文件-

#!/usr/bin/perl

# Display all the files in /tmp directory.
$dir = "/tmp/*";
my @files = glob( $dir );

foreach (@files ){
   print $_ . "
";
}

# Display all the C source files in /tmp directory.
$dir = "/tmp/*.c";
@files = glob( $dir );

foreach (@files ){
   print $_ . "
";
}

# Display all the hidden files.
$dir = "/tmp/.*";
@files = glob( $dir );
foreach (@files ){
   print $_ . "
";
}

# Display all the files from /tmp and /home directories.
$dir = "/tmp/* /home/*";
@files = glob( $dir );

foreach (@files ){
   print $_ . "
";
}

这是另一个例子,它打开一个目录并列出此目录中可用的所有文件。

#!/usr/bin/perl

opendir (DIR, ".") or die "Couldn"t open directory, $!";
while ($file = readdir DIR) {
   print "$file
";
}
closedir DIR;

打印C源文件列表的另一个例子可能是 -

#!/usr/bin/perl

opendir(DIR, ".") or die "Couldn"t open directory, $!";
foreach (sort grep(/^.*.c$/,readdir(DIR))){
   print "$_
";
}
closedir DIR;

创建新的目录

您可以使用mkdir函数创建一个新的目录。您将需要拥有创建目录所需的权限。

#!/usr/bin/perl

$dir = "/tmp/perl";

# This creates perl directory in /tmp directory.
mkdir( $dir ) or die "Couldn"t create $dir directory, $!";
print "Directory created successfully
";

删除目录

您可以使用rmdir函数来删除目录。您需要具有删除目录所需的权限。此外,此目录应该是空的,然后再尝试删除它。

#!/usr/bin/perl

$dir = "/tmp/perl";

# This removes perl directory from /tmp directory.
rmdir( $dir ) or die "Couldn"t remove $dir directory, $!";
print "Directory removed successfully
";

更改目录

您可以使用chdir函数更改目录并转到新位置。您将需要具有所需的权限才能更改目录并进入新目录。

#!/usr/bin/perl

$dir = "/home";

# This changes perl directory  and moves you inside /home directory.
chdir( $dir ) or die "Couldn"t go inside $dir directory, $!";
print "Your new location is $dir
";

Perl - 错误处理

执行和错误总是在一起。如果你打开一个不存在的文件。那么如果您没有正确处理这种情况,那么您的程序被认为是质量差的。

如果发生错误,程序将停止。因此,使用适当的错误处理来处理可能在程序执行期间发生的各种类型的错误,并采取适当的措施,而不是完全停止程序。

您可以通过多种不同的方式识别并捕获错误。它很容易在Perl中捕获错误,然后正确处理它们。这里有几种可以使用的方法。

if语句

当您需要从语句中检查返回值时if语句是明显的选择; 例如 -

if(open(DATA, $file)){
   ...
}else{
   die "Error: Couldn"t open the file - $!";
}

这里变量$!返回实际的错误消息。或者,我们可以在有意义的情况下将声明减少到一行; 例如 -

open(DATA, $file) || die "Error: Couldn"t open the file $!";

除功能

,除非功能是逻辑相反,如果:语句可以完全绕过成功状态,如果表达式的返回false仅被执行。例如 -

unless(chdir("/etc")){
   die "Error: Can"t change directory - $!";
}

除非当你想抛出一个错误或者替代只有表达式失败语句是最好的使用。当在单行语句中使用时,该声明也是有意义的 -

die "Error: Can"t change directory!: $!" unless(chdir("/etc"));

在这里,只有在chdir操作失败的情况下,我们才会死亡,它读取的很好。

三元运算符

对于非常短的测试,您可以使用条件运算符?:

print(exists($hash{value}) ? "There" : "Missing","
");

这不是这么清楚这里是我们正在努力实现的,但效果是一样的使用如果除非声明。当您希望快速返回表达式或语句中的两个值之一时,条件运算符最适合使用。

警告功能

警告功能只是引发一个警告,一条消息被打印到STDERR,但不采取进一步的措施。因此,如果您只想为用户打印警告并继续执行操作,这将更为有用 -

chdir("/etc") or warn "Can"t change directory";

模具功能

模具功能与警告一样工作,除了它也调用exit。在正常脚本中,此函数具有立即终止执行的效果。如果程序中有错误,您应该使用此功能来防止进行操作 -

chdir("/etc") or die "Can"t change directory";

模块内的错误

有两种不同的情况我们应该能够处理 -

警告模具的功能运作方式稍有不同,从一个模块中调用时,你会期望。例如,简单模块 -

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   warn "Error in module!";
}
1;

当从下面的脚本调用时 -

use T;
function();

输出结果如下 -

Error in module! at T.pm line 9.

这或多或少是你可能期望的,但不一定是你想要的。从模块程序员的角度来看,信息是有用的,因为它有助于指出模块本身的错误。对于最终用户,所提供的信息是相当无用的,除了硬件程序员之外,所有信息是完全没有意义的。

这种问题的解决方案是Carp模块,它提供了一种简化的方法来报告模块中的错误信息,返回有关调用脚本的信息。鲤鱼模块提供了四种功能:鲤鱼,clu ck,cro ak和认罪。这些功能将在下面探讨。

鲤鱼功能

鲤鱼功能是等同于警告的基本功能,并将消息打印到STDERR,而不会实际退出脚本并打印脚本名称。

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   carp "Error in module!";
}
1;

当从下面的脚本调用时 -

use T;
function();

输出结果如下 -

Error in module! at test.pl line 4

神秘功能

clu ck car function car car car car car car car。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp qw(cluck);

sub function {
   cluck "Error in module!";
}
1;

当从下面的脚本调用时 -

use T;
function();

输出结果如下 -

Error in module! at T.pm line 9
   T::function() called at test.pl line 4

呱呱声功能

叫声函数等同于模具,不同之处在于它报告主叫一层。像死机一样,在将错误报告给STDERR之后,此函数也退出脚本 -

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   croak "Error in module!";
}
1;

当从下面的脚本调用时 -

use T;
function();

输出结果如下 -

Error in module! at test.pl line 4

与鲤鱼一样,根据警告和死亡功能,包括线和文件信息的相同基本规则适用。

承认功能

忏悔的功能就像是咕咕 ; 它调用die,然后将堆栈跟踪一直打印到起始脚本。

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   confess "Error in module!";
}
1;

当从下面的脚本调用时 -

use T;
function();

输出结果如下 -

Error in module! at T.pm line 9
   T::function() called at test.pl line 4

Perl - 特殊变量

在Perl中有一些具有预定义和特殊含义的变量。它们是在通常的变量指示符($,@或%)之后使用标点符号的变量,如$ _(如下所述)。

大多数特殊变量有一个英文像长名字,例如,操作系统错误变量$!可以写成$ OS_ERROR。但是,如果你要使用英文的名字,那么你必须使用一行英文; 在您的程序文件的顶部。这指导了解释器来获取变量的确切含义。

最常用的特殊变量是$ _,它包含默认输入和模式搜索字符string。例如,在以下行中 -

#!/usr/bin/perl

foreach ("hickory","dickory","doc") {
   print $_;
   print "
";
}

执行时,将产生以下结果 -

hickory
dickory
doc

再次,让我们检查同一个例子,而不使用$ _变量显式 -

#!/usr/bin/perl

foreach ("hickory","dickory","doc") {
   print;
   print "
";
}

执行时,这也将产生以下结果 -

hickory
dickory
doc

第一次执行循环,打印“山核桃”。第二次打印“dickory”,第三次打印“doc”。这是因为在循环的每次迭代中,当前的字符string都放在$ _中,并且默认使用print。以下是Perl将假设$ _即使您没有指定它的地方 -

特殊变量类型

根据特殊变量的用法和性质,我们可以将它们分为以下几类:

全局标量特殊变量

以下是所有标量特殊变量的列表。我们列出了相应的英文名称以及符号名称。

$ _ 默认输入和模式搜索空间。
$ ARG
$。 读取的最后一个文件句柄的当前输入行号。文件句柄上的显式关闭将重置行号。
$ NR
$ / 输入记录分隔符; 默认换行。如果设置为空字符string,则将空行视为分隔符。
$ RS
$, 打印操作符的输出字段分隔符。
$ OFS
$ 打印操作符的输出记录分隔符。
$ ORS
$“ 像“$”一样,除了它适用于内插到双引号字符string(或类似的解释字符string)的列表值。默认是空格。
$ LIST_SEPARATOR
$; 用于多维数组仿真的下标分隔符。默认值为“ 034”。
$ SUBSCRIPT_SEPARATOR
$ ^ L 输出格式以执行换页。默认为“ f”。
$ FORMAT_FORMFEED
$: 当前字符集,之后可能会破坏一个字符string以填充连续字段(以^开头)。默认为“ n”“。
$ FORMAT_LINE_BREAK_CHARACTERS
$ ^ A 写入累加器的格式线的当前值。
$ ACCUMULATOR
$# 包含打印数字的输出格式(不建议使用)。
$ OFMT
$? 最后一个管道返回的状态,backtick(``)命令或系统操作符。
$ CHILD_ERROR
$! 如果在数字上下文中使用,则会生成errno变量的当前值,从而识别最后一次系统调用错误。如果在字符string上下文中使用,则会生成相应的系统错误字符string。
$ OS_ERROR或$ ERRNO
$ @ 来自最后一个eval命令的Perl语法错误消息。
$ EVAL_ERROR
$$ 运行此脚本的Perl进程的pid。
$ PROCESS_ID或$ PID
$ < 这个进程的真实用户ID(uid)。
$ REAL_USER_ID或$ UID
$> 此过程的有效用户ID。
$ EFFECTIVE_USER_ID或$ EUID
$( 该进程的实际组ID(gid)。
$ REAL_GROUP_ID或$ GID
$) 这个过程的有效的gid。
$ EFFECTIVE_GROUP_ID或$ EGID
$ 0 包含正在执行的Perl脚本的文件的名称。
$ PROGRAM_NAME
$ [ 数组中第一个元素的索引和子字符string中的第一个字符。默认值为0。
$] 返回版本加上修补程序除以1000。
$ PERL_VERSION
$ ^ D 调试标志的当前值。
$ DEBUGGING
$ ^ E 某些平台上的扩展错误消息。
$ EXTENDED_OS_ERROR
$ ^ F 最大系统文件描述符,通常为2。
$ SYSTEM_FD_MAX
$ ^ H 包含由某些实用模块启用的内部编译器提示。
$ ^ I 现场编辑扩展的当前值。使用undef禁用在线编辑。
$ INPLACE_EDIT
$ ^ M 如果Perl死于内存不足错误,$ M的内容可用作紧急内存池。使用$ M需要特殊的Perl编译。有关详细信息,请参阅INSTALL文档。
$ ^ O 包含编译当前Perl二进制文件的操作系统的名称。
$ OSNAME
$ ^ P 调试器清除的内部标志,使其不会自动调试。
$ PERLDB
$ ^ T 脚本开始运行的时间,从时代开始的几秒钟。
$ BASETIME
$ ^ W 警告switch的当前值,为true或false。
$警告
$ ^ X Perl二进制本身被执行的名称。
$ EXECUTABLE_NAME
$ ARGV 包含从<ARGV>读取时当前文件的名称。

全局数组特殊变量

@ARGV 该数组包含用于该脚本的命令行参数。
@INC 该数组包含要由do,require或use结构来评估Perl脚本的位置列表。
@F 当给出命令行switch时,输入线分割的数组。

全局哈希特殊变量

%INC 包含通过do或require所包含的每个文件的文件名的条目的哈希值。
%ENV 包含您当前环境的哈希值。
%SIG 用于为各种信号设置信号处理程序的哈希值。

全球特殊文件处理

ARGV 在@ARGV中复制命令行文件名的特殊文件句柄。通常在<>中写为空文件句柄。
STDERR 任何包中标准错误的特殊文件句柄。
STDIN 任何包装中标准输入的特殊文件柄。
STDOUT 任何包装中标准输出的特殊文件句柄。
数据 引用包含脚本的文件中__END__个令牌之后的任何东西的特殊文件句柄。或者,在所需文件中的__DATA__令牌之后的任何特殊文件句柄,只要您在同一个包__DATA__中读取数据即可。
_(下划线) 用于缓存最后一个stat,lstat或文件测试运算符的信息的特殊文件句柄。

全球特殊常数

__结束__ 表示程序的逻辑结束。任何以下文本被忽略,但可以通过DATA文件句柄读取。
__文件__ 表示程序使用的位置的文件名。不插入字符string。
__线__ 表示当前行号。不插入字符string。
__包__ 在编译时表示当前的程序包名称,如果没有当前程序包,则表示未定义。不插入字符string。

正则表达式特殊变量

$数位 包含匹配的最后一个模式中相应的括号组匹配的文本。例如,$ 1匹配前一个正则表达式中第一组括号中包含的任何内容。
$& 由最后一个成功的模式匹配匹配的字符string。
$ MATCH
$` 前一个成功模式匹配匹配的字符string。
$ PREMATCH
$" 随后的任何匹配的字符string由最后一个成功的模式匹配。
$ POSTMATCH
$ + 最后一个括号与最后一个搜索模式匹配。如果您不知道一组替代模式中的哪一种是匹配的,这很有用。例如:/ Version:(。*)|修订:(。*)/ &&($ rev = $ +);
$ LAST_PAREN_MATCH

Filehandle特殊变量

$ | 如果设置为非零,则在当前选择的输出通道上每次写入或打印后强制执行fflush(3)。
$ OUTPUT_AUTOFLUSH
$% 当前所选输出通道的当前页码。
$ FORMAT_PAGE_NUMBER
$ = 当前所选输出通道的当前页长(可打印行)。默认为60。
$ FORMAT_LINES_PER_PAGE
$ - 当前所选输出通道页面上剩下的行数。
$ FORMAT_LINES_LEFT
$ 当前所选输出通道的当前报告格式的名称。默认是文件句柄的名称。
$ FORMAT_NAME
$ ^ 当前所选输出通道的当前页首格式的名称。默认是附加了_TOP的文件句柄的名称。
$ FORMAT_TOP_NAME

Perl编码标准

当然,每个程序员都有自己的格式化偏好,但是有一些一般性的指导方针可以使您的程序更容易阅读,理解和维护。

最重要的是在任何时候在-w标志下运行你的程序。您可以通过no警告pragma或$ ^ W变量(如果必须)明确地关闭代码的特定部分。你也应该总是使用严格的或者知道为什么不这样做的原因。使用sigtrap甚至使用诊断编译指示也可能是有用的。

关于代码的美学原理,Larry唯一关心的是多行BLOCK的闭合大括号应该与启动构造的关键字一致。除此之外,他还有其他偏好不太强 -

这里还有一些其他更实质的风格问题要考虑:只是因为你可以做某些特定的方式并不意味着你应该这样做。Perl旨在为您提供多种方法来做任何事情,因此请考虑选择最可读的。例如 -

open(FOO,$foo) || die "Can"t open $foo: $!";

比 -

die "Can"t open $foo: $!" unless open(FOO,$foo);

因为第二种方式隐藏在修饰符中的语句的主要点。另一方面,

print "Starting analysis
" if $verbose;

比 -

$verbose && print "Starting analysis
";

因为主要的不是用户是否键入-v。

当Perl提供最后一个操作符,您可以在中间退出时,不要通过愚蠢的扭曲来退出顶部或底部的循环。只是“过得”一点,使它更明显 -

LINE:
for (;;) {
   statements;
   last LINE if $foo;
   next LINE if /^#/;
   statements;
}

我们再来看几个重点 -

opendir(D, $dir) or die "can"t opendir $dir: $!";

Perl - 正则表达式

正则表达式是一个字符string,用于定义您正在查看的模式或模式。Perl中正则表达式的语法非常类似于您将在其他正则表达式支持程序(如sedgrepawk)中找到的内容

应用正则表达式的基本方法是使用模式绑定运算符=和第一个运算符是一个测试和赋值运算符。

Perl中有三个正则表达式运算符。

每种情况下的正斜杠都用作正在指定的正则表达式(正则表达式)的分隔符。如果您对任何其他分隔符感到舒服,那么您可以使用正斜杠。

匹配运算符

匹配运算符m //用于将字符string或语句与正则表达式匹配。例如,要将字符序列“foo”与标量$ bar相匹配,可以使用如下语句 -

#!/usr/bin/perl

$bar = "This is foo and again foo";
if ($bar =~ /foo/){
   print "First time is matching
";
}else{
   print "First time is not matching
";
}

$bar = "foo";
if ($bar =~ /foo/){
   print "Second time is matching
";
}else{
   print "Second time is not matching
";
}

当执行上述程序时,输出结果如下-

First time is matching
Second time is matching

m //实际上与q //运算符序列相同的方式工作。您可以使用自然匹配字符的任意组合作为表达式的分隔符。例如,m {},m()和m> <都是有效的。所以上面的例子可以重写如下 -

#!/usr/bin/perl

$bar = "This is foo and again foo";
if ($bar =~ m[foo]){
   print "First time is matching
";
}else{
   print "First time is not matching
";
}

$bar = "foo";
if ($bar =~ m{foo}){
   print "Second time is matching
";
}else{
   print "Second time is not matching
";
}

如果分隔符是正斜杠,则可以从m //中省略m,但对于所有其他分隔符,您必须使用m前缀。

请注意,如果表达式匹配,则整个匹配表达式,即=或!左侧的表达式和匹配运算符返回true(在标量上下文中)。所以声明 -

$true = ($foo =~ m/foo/);

如果$ foo与正则表达式匹配,则将$ true设置为1,如果匹配失败,则将为0。在列表上下文中,匹配返回任何分组表达式的内容。例如,当从时间字符string中提取小时,分钟和秒时,我们可以使用 -

my ($hours, $minutes, $seconds) = ($time =~ m/(d+):(d+):(d+)/);

匹配运算符修饰符

匹配运算符支持自己的一组修饰符。/ g修改器允许全局匹配。/ i修饰符将使匹配大小写不区分大小写。以下是修饰符的完整列表

没有 修饰和说明
1。 一世

使比赛大小写不敏感。

2。 m

指定如果字符string具有换行符或回车符,则^和$运算符现在将与换行符相匹配,而不是字符string边界。

3。 o

仅表达一次表达式。

4。 s

允许使用。以匹配换行符。

5。 X

为了清楚起见,允许您在表达式中使用空格。

6。 G

全球查找所有比赛。

7。 cg

允许搜索在全局匹配失败后继续进行。

只匹配一次

还有一个更简单的匹配运算符版本--PATTERN?操作符。这与m //运算符基本相同,只是它在每次调用重置之间搜索的字符string中只匹配一次。

例如,您可以使用它来获取列表中的第一个和最后一个元素 -

#!/usr/bin/perl

@list = qw/food foosball subeo footnote terfoot canic footbrdige/;

foreach (@list)
{
   $first = $1 if ?(foo.*)?;
   $last = $1 if /(foo.*)/;
}
print "First: $first, Last: $last
";

当执行上述程序时,输出结果如下-

First: food, Last: footbrdige

正则表达式变量

正则表达式变量包括$,它包含最后一个匹配匹配的分组匹配; $&,其中包含整个匹配的字符string; $`,其中包含匹配字符string之前的所有内容; $",其中包含匹配字符string后的所有内容。以下代码演示结果 -

#!/usr/bin/perl

$string = "The food is in the salad bar";
$string =~ m/foo/;
print "Before: $`
";
print "Matched: $&
";
print "After: $"
";

当执行上述程序时,输出结果如下-

Before: The
Matched: foo
After: d is in the salad bar

替代操作符

替换运算符s ///实际上只是匹配运算符的扩展,可以让您替换与某些新文本匹配的文本。运算符的基本形式是 -

s/PATTERN/REPLACEMENT/;

PATTERN是我们正在寻找的文本的正则表达式。REPLACEMENT是我们要用来替换找到的文本的文本或正则表达式的规范。例如,我们可以更换所有出现的使用下面的正则表达式-

#/user/bin/perl

$string = "The cat sat on the mat";
$string =~ s/cat/dog/;

print "$string
";

当执行上述程序时,输出结果如下-

The dog sat on the mat

替换操作符修饰符

以下是与替换运算符一起使用的所有修饰符的列表。

没有 修饰和说明
1。 一世

使比赛大小写不敏感。

2。 m

指定如果字符string具有换行符或回车符,则^和$运算符现在将与换行符相匹配,而不是字符string边界。

3。 o

仅表达一次表达式。

4。 s

允许使用。以匹配换行符。

5。 X

为了清楚起见,允许您在表达式中使用空格。

6。 G

使用替换文本替换发现的表达式的所有出现。

7。 e

评估替换,就像它是一个Perl语句,并使用其返回值作为替换文本。

翻译经营者

翻译与替代原则相似但并不完全相同,但与替代不同,翻译(或音译)不使用正则表达式来进行替换值搜索。翻译经营者是 -

tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds

翻译将使用REPLACEMENTLIST中的相应字符替换SEARCHLIST中所有出现的字符。例如,使用“猫坐在垫子上”。我们在本章中一直使用的字符string -

#/user/bin/perl

$string = "The cat sat on the mat";
$string =~ tr/a/o/;

print "$string
";

当执行上述程序时,输出结果如下-

The cot sot on the mot.

也可以使用标准Perl范围,允许您通过字母或数值来指定字符的范围。要更改字符string的大小写,可以使用以下语法代替uc函数。

$string =~ tr/a-z/A-Z/;

翻译操作符修饰符

以下是与翻译相关的运算符列表。

没有 修饰和说明
1。 C

完成搜索列表。

2。 d

删除找到但未放置的字符。

3。 s

倒数重复替换字符。

/ d修饰符将删除与REPLACEMENTLIST中没有相应条目的SEARCHLIST匹配的字符。例如 -

#!/usr/bin/perl 

$string = "the cat sat on the mat.";
$string =~ tr/a-z/b/d;

print "$string
";

当执行上述程序时,输出结果如下-

b b   b.

最后一个修饰符/ s删除被替换的字符的重复序列,所以 -

#!/usr/bin/perl

$string = "food";
$string = "food";
$string =~ tr/a-z/a-z/s;

print "$string
";

当执行上述程序时,输出结果如下-

fod

更复杂的正则表达式

你不一定要匹配固定的字符string。事实上,你可以通过使用更复杂的正则表达式来匹配任何你想要的东西。这是一个快速的备忘单 -

下表列出了Python中可用的正则表达式语法。

没有 图案和描述
1。 ^

匹配开始行

2。 $

匹配行尾。

3。

匹配除换行符以外的任何单个字符。使用m选项可以使其匹配换行符。

4。 [...]

匹配括号中的任何单个字符。

5。 [^ ...]

匹配不在括号中的任何单个字符。

6。 *

匹配0或更多出现前面的表达式。

7。 +

匹配1个或多个前面表达式的出现。

8。

匹配0或1出现前面的表达式。

9。 {n}

匹配正好n个前面表达式的出现次数。

10。 {n,}

匹配前面表达式出现n次或更多次。

11。 {n,m}

匹配至少n个和最多m个先前表达式的出现。

11。 a | b

匹配a或b。

12。 w

匹配字符字符

13。 W

匹配非字符字符。

14。 s

匹配空格 相当于[ t n r f]。

15。 S

匹配非空格。

16。 d

匹配数字 相当于[0-9]。

17。 D

匹配不一致

18。 一个

匹配字符string开始。

19。 Z

匹配字符string的结尾。如果存在换行符,则它将在换行符之前匹配。

20。 z

匹配字符string的结尾。

21。 G

比赛最后一场比赛结束。

22。 b

外部括号匹配字边界。在括号内匹配退格(0x08)。

23。 B

匹配非字边界。

24。 n, t等等

匹配换行符,回车符,制表符等

25。 1 ... 9

匹配第n个分组子表达式。

26。 10

匹配第n个分组子表达式,如果它已经匹配。否则指的是字符代码的八进制表示。

27。 [aeiou]

匹配给定集合中的单个字符

28。 [^ aeiou]

匹配给定集合外的单个字符

^元字符与字符string的开头匹配,$ metasymbol匹配字符string的末尾。这里有一些简单的例子。

# nothing in the string (start and end are adjacent)
/^$/   

# a three digits, each followed by a whitespace
# character (eg "3 4 5 ")
/(ds){3}/  

# matches a string in which every
# odd-numbered letter is a (eg "abacadaf")
/(a.)+/  

# string starts with one or more digits
/^d+/

# string that ends with one or more digits
/d+$/

让我们看看另一个例子。

#!/usr/bin/perl

$string = "Cats go Catatonic
When given Catnip";
($start) = ($string =~ /A(.*?) /);
@lines = $string =~ /^(.*?) /gm;
print "First word: $start
","Line starts: @lines
";

当执行上述程序时,输出结果如下-

First word: Cats
Line starts: Cats When

匹配边界

b在任何字边界匹配时,由 W类和 W类之间的差值所限定的。因为 w包含一个单词的字符,而 W是相反的,这通常意味着一个单词的终止。断言这不是一个单词边界的任意位置相匹配。例如 -

/cat/ # Matches "the cat sat" but not "cat on the mat"
/BcatB/ # Matches "verification" but not "the cat on the mat"
/catB/ # Matches "catatonic" but not "polecat"
/Bcat/ # Matches "polecat" but not "catatonic"

选择替代品

| 字符就像Perl中的标准或按位OR。它指定正则表达式或组中的替代匹配。例如,要在表达式中匹配“cat”或“dog”,可以使用这个 -

if ($string =~ /cat|dog/)

您可以将表达式的各个元素组合在一起,以支持复杂的匹配。搜索两个人的名字可以通过两个单独的测试来实现,像这样 -

if (($string =~ /Martin Brown/) ||  ($string =~ /Sharon Brown/))

This could be written as follows

if ($string =~ /(Martin|Sharon) Brown/)

分组匹配

从正则表达的角度来看,除了前者稍微更清楚之外,没有区别。

$string =~ /(S+)s+(S+)/;

and 

$string =~ /S+s+S+/;

然而,分组的好处是它允许我们从正则表达式中提取序列。分组作为列表以按原样显示的顺序返回。例如,在以下片段中,我们从字符string中抽出了小时,分钟和秒。

my ($hours, $minutes, $seconds) = ($time =~ m/(d+):(d+):(d+)/);

除了这种直接方法之外,匹配组也可以在特殊的$ x变量中使用,其中x是正则表达式中组的编号。因此,我们可以重写前面的例子如下:

#!/usr/bin/perl

$time = "12:05:30";

$time =~ m/(d+):(d+):(d+)/;
my ($hours, $minutes, $seconds) = ($1, $2, $3);

print "Hours : $hours, Minutes: $minutes, Second: $seconds
";

当执行上述程序时,输出结果如下-

Hours : 12, Minutes: 05, Second: 30

在替换表达式中使用组时,可以在替换文本中使用$ x语法。因此,我们可以使用此格式重新格式化日期字符string -

#!/usr/bin/perl

$date = "03/26/1999";
$date =~ s#(d+)/(d+)/(d+)#$3/$1/$2#;

print "$date
";

当执行上述程序时,输出结果如下-

1999/03/26

G断言

G断言允许您从最后一次匹配发生的位置继续搜索。例如,在下面的代码中,我们使用 G,以便我们可以搜索到正确的位置,然后提取一些信息,而不必创建一个更复杂的单个正则表达式 -

#!/usr/bin/perl

$string = "The time is: 12:31:02 on 4/12/00";

$string =~ /:s+/g;
($time) = ($string =~ /G(d+:d+:d+)/);
$string =~ /.+s+/g;
($date) = ($string =~ m{G(d+/d+/d+)});

print "Time: $time, Date: $date
";

当执行上述程序时,输出结果如下-

Time: 12:31:02, Date: 4/12/00

G断言实际上只是pos函数的metasymbol等价物,因此在正则表达式调用之间,您可以继续使用pos,甚至通过使用pos作为左值子例程来修改pos(因此 G)的值。

正则表达式示例

字面字符

没有 示例和说明
1。 Perl

匹配“Perl”。

字符类

没有 示例和说明
1。 [Pp] yyon

匹配“Python”或“python”

2。 揉搓

匹配“ruby”或“rube”

3。 [aeiou]

匹配任何一个小写元音

4。 [0-9]

匹配任何数字; 与[0123456789]

5。 [az]

匹配任何小写ASCII字母

6。 [AZ]

匹配任何大写的ASCII字母

7。 [a-zA-Z0-9]

匹配上述任何一个

8。 [^ aeiou]

匹配除小写元音之外的任何东西

9。 [^ 0-9]

匹配除数字以外的任何内容

特殊字符类

没有 示例和说明
1。

匹配除换行符以外的任何字符

2。 d

匹配数字:[0-9]

3。 D

比较不合格:[^ 0-9]

4。 s

匹配空格字符:[ t r n f]

5。 S

匹配非空格:[^ t r n f]

6。 w

匹配单字字符:[A-Za-z0-9_]

7。 W

匹配非字符:[^ A-Za-z0-9_]

重复案例

没有 示例和说明
1。 红宝石?

匹配“rub”或“ruby”:y是可选的

2。 红宝石*

匹配“擦”加0或更多ys

3。 红宝石+

匹配“擦”加1个或更多的y

4。 d {3}

完全匹配3位数

5。 d {3,}

匹配3位或更多位数字

6。 d {3,5}

匹配3,4或5位数

不朽重复

这匹配最小的重复次数 -

没有 示例和说明
1。 <。*>

贪婪重复:匹配“<python> perl>”

2。 <。*?>

Nongreedy:在“<python> perl”中匹配“<python>”

用圆括号分组

没有 示例和说明
1。 D d +

没有组:+重复 d

2。 ( D d)+

分组:+重复 D d对

3。 ([Pp] ython(,)?)+

匹配“Python”,“Python,python,python”等

反向引用

这与以前匹配的组再次匹配 -

没有 示例和说明
1。 ([Pp])ython& 1ails

匹配python和pails或Python和Pails

2。 (["“])[^ 1] * 1

单引号或双引号字符string。 1匹配第一组匹配。 2匹配任何第二组匹配等

备择方案

没有 示例和说明
1。 python | perl

匹配“python”或“Perl”

2。 擦(y | le))

匹配“红宝石”或“卢布”

3。 Python(!+ | ?)

“Python”后跟一个或多个!还是一个?

锚点

这需要指定匹配位置。

没有 示例和说明
1。 ^ Python

在字符string或内部行的开头匹配“Python”

2。 Python $

匹配字符string或行末尾的“Python”

3。 APython

匹配字符string开头的“Python”

4。 Python Z

匹配字符string末尾的“Python”

5。 bPython b

在字边界匹配“Python”

6。 brub B

B是非字边界:在“rube”和“ruby”中匹配“rub”,而不是单独

7。 Python(?=!)

匹配“Python”,如果紧跟感叹号

8。 蟒蛇(?!!)

匹配“Python”,如果不跟着感叹号

带括号的特殊语法

没有 示例和说明
1。 R(?#注释)

匹配“R”。其余的都是注释

2。 R(?i)uby

匹配“uby”时不区分大小写

3。 R(?i:uby)

与上述相同

4。 擦(?:y | le))

仅组合而不创建 1反向引用

Perl - 发送电子邮件

使用sendmail实用程序

发送纯粹的消息

如果您正在使用Linux / Unix机器,那么您可以在Perl程序中简单地使用sendmail实用程序来发送电子邮件。这是一个示例脚本,可以向给定的电子邮件ID发送电子邮件。只需确保sendmail实用程序的给定路径是正确的。对于您的Linux / Unix机器可能会有所不同。

#!/usr/bin/perl
 
$to = "abcd@gmail.com";
$from = "webmaster@yourdomain.com";
$subject = "Test Email";
$message = "This is test email sent by Perl Script";
 
open(MAIL, "|/usr/sbin/sendmail -t");
 
# Email Header
print MAIL "To: $to
";
print MAIL "From: $from
";
print MAIL "Subject: $subject

";
# Email Body
print MAIL $message;

close(MAIL);
print "Email Sent Successfully
";

实际上,上述脚本是一个客户端电子邮件脚本,它将起草电子邮件并提交给在Linux / Unix机器上本地运行的服务器。此脚本将不负责将电子邮件发送到实际目的地。因此,您必须确保电子邮件服务器在您的计算机上正确配置并运行,以发送电子邮件给给定的电子邮件ID。

发送HTML消息

如果要使用sendmail发送HTML格式的电子邮件,那么您只需要在电子邮件的标题部分中添加Content-type:text / html n,如下所示:

#!/usr/bin/perl
 
$to = "abcd@gmail.com";
$from = "webmaster@yourdomain.com";
$subject = "Test Email";
$message = "<h1>This is test email sent by Perl Script</h1>";
 
open(MAIL, "|/usr/sbin/sendmail -t");
 
# Email Header
print MAIL "To: $to
";
print MAIL "From: $from
";
print MAIL "Subject: $subject

";
print MAIL "Content-type: text/html
";
# Email Body
print MAIL $message;

close(MAIL);
print "Email Sent Successfully
";

使用MIME :: Lite模块

如果您正在使用Windows机器,那么您将无法访问sendmail实用程序。但您可以使用MIME:Lite perl模块编写自己的电子邮件客户端。您可以从MIME-Lite-3.01.tar.gz下载此模块,并将其安装在您的任一机器Windows或Linux / Unix上。要安装它遵循简单的步骤 -

$tar xvfz MIME-Lite-3.01.tar.gz
$cd MIME-Lite-3.01
$perl Makefile.PL
$make
$make install

就是这样,你的机器上会安装MIME :: Lite模块。现在您可以使用下面介绍的简单脚本发送您的电子邮件。

发送纯粹的消息

现在以下是一个脚本,将照顾发送电子邮件给给定的电子邮件ID -

#!/usr/bin/perl
use MIME::Lite;
 
$to = "abcd@gmail.com";
$cc = "efgh@mail.com";
$from = "webmaster@yourdomain.com";
$subject = "Test Email";
$message = "This is test email sent by Perl Script";

$msg = MIME::Lite->new(
                 From     => $from,
                 To       => $to,
                 Cc       => $cc,
                 Subject  => $subject,
                 Data     => $message
                 );
                 
$msg->send;
print "Email Sent Successfully
";

发送HTML消息

如果要使用sendmail发送HTML格式的电子邮件,那么您只需要在电子邮件的标题部分中添加Content-type:text / html n以下是脚本,它将照顾发送HTML格式的电子邮件 -

#!/usr/bin/perl
use MIME::Lite;
 
$to = "abcd@gmail.com";
$cc = "efgh@mail.com";
$from = "webmaster@yourdomain.com";
$subject = "Test Email";
$message = "<h1>This is test email sent by Perl Script</h1>";

$msg = MIME::Lite->new(
                 From     => $from,
                 To       => $to,
                 Cc       => $cc,
                 Subject  => $subject,
                 Data     => $message
                 );
                 
$msg->attr("content-type" => "text/html");         
$msg->send;
print "Email Sent Successfully
";

发送附件

如果你想发送一个附件,那么下面的脚本用于这个目的 -

#!/usr/bin/perl
use MIME::Lite;
 
$to = "abcd@gmail.com";
$cc = "efgh@mail.com";
$from = "webmaster@yourdomain.com";
$subject = "Test Email";
$message = "This is test email sent by Perl Script";

$msg = MIME::Lite-=>new(
                 From     => $from,
                 To       => $to,
                 Cc       => $cc,
                 Subject  => $subject,
                 Type     => "multipart/mixed"
                 );
                 
# Add your text message.
$msg->attach(Type         => "text",
             Data         => $message
             );
            
# Specify your file as attachement.
$msg->attach(Type         => "image/gif",
             Path         => "/tmp/logo.gif",
             Filename     => "logo.gif",
             Disposition  => "attachment"
            );       
$msg->send;
print "Email Sent Successfully
";

您可以使用attach()方法在电子邮件中附加尽可能多的文件。

使用SMTP服务器

如果您的计算机没有运行电子邮件服务器,那么您可以使用远程位置可用的任何其他电子邮件服务器。但是要使用任何其他电子邮件服务器,您需要具有id,其密码,URL等。一旦您拥有所需的所有信息,您需要简单地以send()方法提供以下信息:

$msg->send("smtp", "smtp.myisp.net", AuthUser=>"id", AuthPass=>"password" );

您可以联系您的电子邮件服务器管理员以获取上述使用的信息,如果用户标识和密码尚不可用,则您的管理员可以在几分钟内创建它。

Perl - 套接字编程

什么是套接字?

Socket是在不同进程之间创建虚拟双工连接的Berkeley UNIX机制。随后将其移植到每个已知操作系统上,实现跨不同操作系统软件运行的地理位置之间的系统之间的通信。如果不是套接字,系统之间的大部分网络通信永远不会发生。

仔细看看 网络上的典型计算机系统根据需要在其上运行的各种应用接收和发送信息。该信息被路由到系统,因为指定了唯一的IP地址。在系统上,这些信息被给予相应的应用程序,这些应用程序在不同的端口上进行监听。例如,互联网浏览器在端口80上监听从Web服务器接收到的信息。此外,我们还可以编写可以侦听和发送/接收特定端口号信息的自定义应用程序。

现在,我们总结一个套接字是一个IP地址和一个端口,使连接能够通过网络发送和接收数据。

为了解释上述套接字概念,我们将以Perl为例介绍客户端 - 服务器编程。要完成客户端服务器架构,我们必须执行以下步骤:

创建服务器

创建客户端

下图显示了客户端和服务器使用的呼叫的完整顺序 -

Perl套接字

服务器端套接字呼叫

socket()调用

插座()调用是在建立网络连接创建套接字的第一个电话。此调用具有以下语法 -

socket( SOCKET, DOMAIN, TYPE, PROTOCOL );

上述调用创建一个SOCKET,其他三个参数是整数,应为TCP / IP连接设置以下值。

所以socket服务器发出的socket函数调用就是这样的 -

use Socket     # This defines PF_INET and SOCK_STREAM

socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname("tcp"))[2]);

bind()调用

由socket()调用创建的套接字在被绑定到主机名和端口号之前是无用的。服务器使用以下bind()函数来指定他们将接受来自客户端的连接的端口。

bind( SOCKET, ADDRESS );

这里SOCKET是由socket()调用返回的描述符,ADDRESS是一个包含三个元素的套接字地址(TCP / IP)

由于bind()被服务器使用,不需要知道自己的地址,所以参数列表看起来像这样 -

use Socket        # This defines PF_INET and SOCK_STREAM

$port = 12345;    # The unique port used by the sever to listen requests
$server_ip_address = "10.12.12.168";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can"t bind to port $port! 
";

the or die子句非常重要,因为如果服务器没有未连接的情况下死机,除非您使用setsockopt()函数使用选项SO_REUSEADDR,端口将不会立即重新使用这里使用pack_sockaddr_in()函数将端口和IP地址打包成二进制格式。

listen()调用

如果这是一个服务器程序,那么需要在指定的端口上发出一个listen()调用来监听,也就是等待传入的请求。此调用具有以下语法 -

listen( SOCKET, QUEUESIZE );

上述调用使用由socket()调用返回的SOCKET描述符,并且QUEUESIZE是同时允许的未完成连接请求的最大数量。

accept()调用

如果这是一个服务器程序,则需要发出对access()函数的调用以接受传入的连接。此调用具有以下语法 -

accept( NEW_SOCKET, SOCKET );

接受调用接收由socket()函数返回的SOCKET描述符,并且在成功完成后,将为客户端和服务器之间的所有将来的通信返回一个新的套接字描述符NEW_SOCKET。如果access()调用失败,那么它返回在最初使用的Socket模块中定义的FLASE。

一般来说,accept()用于无限循环。一旦一个连接到达,服务器就会创建一个子进程来处理它或自己服务,然后返回来监听更多的连接。

while(1) {
   accept( NEW_SOCKET, SOCKT );
   .......
}

现在所有与服务器相关的呼叫都已经结束,让我们看到一个客户端需要的呼叫。

客户端套接字呼叫

connect()调用

如果要准备客户端程序,那么首先您将使用socket()调用来创建一个套接字,然后您将不得不使用connect()调用连接到服务器。您已经看到了socket()调用语法,它将保持类似于服务器socket()调用,但这里是connect()调用的语法-

connect( SOCKET, ADDRESS );

这里SCOKET是由客户端发出的socket()调用返回的套接字描述符,ADDRESS是一个类似于绑定调用的套接字地址,但它包含远程服务器的IP地址。

$port = 21;    # For example, the ftp port
$server_ip_address = "10.12.12.168";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server_ip_address)))
   or die "Can"t connect to port $port! 
";

如果您成功连接到服务器,则可以使用SOCKET描述符开始将命令发送到服务器,否则您的客户端将出现错误消息。

客户端 - 服务器示例

以下是使用Perl套接字实现简单客户端 - 服务器程序的Perl代码。这里服务器监听传入请求,一旦建立连接,它只需从服务器回复Smile客户端读取该消息并在屏幕上打印。假设我们的服务器和客户端位于同一台机器上,我们来看看它是如何完成的。

创建服务器的脚本

#!/usr/bin/perl -w
# Filename : server.pl

use strict;
use Socket;

# use port 7890 as default
my $port = shift || 7890;
my $proto = getprotobyname("tcp");
my $server = "localhost";  # Host IP running the server

# create a socket, make it reusable
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
   or die "Can"t open socket $!
";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
   or die "Can"t set socket option to SO_REUSEADDR $!
";

# bind to a port, then listen
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can"t bind to port $port! 
";

listen(SOCKET, 5) or die "listen: $!";
print "SERVER started on port $port
";

# accepting a connection
my $client_addr;
while ($client_addr = accept(NEW_SOCKET, SOCKET)) {
   # send them a message, close connection
   my $name = gethostbyaddr($client_addr, AF_INET );
   print NEW_SOCKET "Smile from the server";
   print "Connection recieved from $name
";
   close NEW_SOCKET;
}

要在后台运行服务器,请在Unix提示符下执行以下命令 -

$perl sever.pl&

创建客户端的脚本

!/usr/bin/perl -w
# Filename : client.pl

use strict;
use Socket;

# initialize host and port
my $host = shift || "localhost";
my $port = shift || 7890;
my $server = "localhost";  # Host IP running the server

# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname("tcp"))[2])
   or die "Can"t create a socket $!
";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
   or die "Can"t connect to port $port! 
";

my $line;
while ($line = <SOCKET>) {
   print "$line
";
}
close SOCKET or die "close: $!";

现在让我们在命令提示符下启动我们的客户端,它将连接到服务器并读取服务器发送的消息,并在屏幕上显示相同的信息,如下所示:

$perl client.pl
Smile from the server

注意 - 如果以点表示法提供实际的IP地址,则建议在客户端和服务器中以相同的格式提供IP地址,以避免混淆。

PERL中的面向对象编程

我们已经在Perl和Perl匿名数组和散列中研究了参考。Perl中面向对象的概念非常基于引用和匿名数组和散列。我们开始学习面向对象Perl的基本概念。

对象基础

从Perl处理对象的角度来看,有三个主要术语。这些术语是对象,类和方法。

Perl提供了一个bless()函数,用于返回最终成为对象的引用。

定义类

在Perl中定义一个类非常简单。一个类最简单的形式对应一个Perl Package。要在Perl中创建一个类,我们首先创建一个包。

软件包是用户定义的变量和子例程的独立单元,可以重复使用。

Perl软件包在Perl程序中提供了一个单独的命名空间,它保持子程序和变量独立于与其他程序包冲突的子程序和变量。

要在Perl中声明一个名为Person的类,我们做 -

package Person;

包定义的范围扩展到文件的末尾,或直到遇到另一个包关键字。

创建和使用对象

要创建一个类(一个对象)的实例,我们需要一个对象构造函数。该构造函数是在程序包中定义的方法。大多数程序员选择将此对象构造方法命名为new,但是在Perl中可以使用任何名称。

您可以在Perl中使用任何类型的Perl变量作为对象。大多数Perl程序员选择引用数组或散列。

让我们使用Perl哈希引用为我们的Person类创建我们的构造函数。创建对象时,需要提供构造函数,该构造函数是返回对象引用的程序包中的子例程。对象引用是通过祝福对程序包类的引用来创建的。例如 -

package Person;
sub new
{
   my $class = shift;
   my $self = {
      _firstName => shift,
      _lastName  => shift,
      _ssn       => shift,
   };
   # Print all the values just for clarification.
   print "First Name is $self->{_firstName}
";
   print "Last Name is $self->{_lastName}
";
   print "SSN is $self->{_ssn}
";
   bless $self, $class;
   return $self;
}

现在让我们看看如何创建一个对象。

$object = new Person( "Mohammad", "Saleem", 23234345);

如果不想将任何值分配给任何类变量,您可以在consturctor中使用简单的哈希。例如 -

package Person;
sub new
{
   my $class = shift;
   my $self = {};
   bless $self, $class;
   return $self;
}

定义方法

其他面向对象语言具有数据安全性的概念,以防止程序员直接改变对象数据,并提供修改对象数据的访问器方法。Perl没有私有变量,但是我们仍然可以使用帮助方法的概念来操纵对象数据。

让我们定义一个帮助方法来获取人的名字 -

sub getFirstName {
    return $self->{_firstName};
}

另一个帮助功能设定人的名字 -

sub setFirstName {
   my ( $self, $firstName ) = @_;
   $self->{_firstName} = $firstName if defined($firstName);
   return $self->{_firstName};
}

现在让我们看看完整的例子:将Person包和帮助函数保存在Person.pm文件中。

#!/usr/bin/perl 

package Person;

sub new
{
   my $class = shift;
   my $self = {
      _firstName => shift,
      _lastName  => shift,
      _ssn       => shift,
   };
   # Print all the values just for clarification.
   print "First Name is $self->{_firstName}
";
   print "Last Name is $self->{_lastName}
";
   print "SSN is $self->{_ssn}
";
   bless $self, $class;
   return $self;
}
sub setFirstName {
   my ( $self, $firstName ) = @_;
   $self->{_firstName} = $firstName if defined($firstName);
   return $self->{_firstName};
}

sub getFirstName {
   my( $self ) = @_;
   return $self->{_firstName};
}
1;

现在让我们在employee.pl文件中使用Person对象,如下所示:

#!/usr/bin/perl

use Person;

$object = new Person( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();

print "Before Setting First Name is : $firstName
";

# Now Set first name using helper function.
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "Before Setting First Name is : $firstName
";

当我们执行上面的程序,它产生以下结果 -

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.

遗产

面向对象编程具有非常好的有用的概念,称为继承。继承只意味着父类的属性和方法将可用于子类。所以你不必一次又一次地编写相同的代码,你可以继承父类。

例如,我们可以有一个Employee类,它继承自Person。这被称为“isa”关系,因为雇员是一个人。Perl有一个特殊变量@ISA来帮助这个。@ISA管理(方法)继承。

以下是使用继承时要考虑的重点 -

所以要创建一个新的Employee类,它将继承Person类中的方法和属性,我们只需编写如下代码:将此代码保存到Employee.pm中。

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person

现在Employee类具有从Person类继承的所有方法和属性,您可以使用它们如下:使用main.pl文件进行测试 -

#!/usr/bin/perl

use Employee;

$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();

print "Before Setting First Name is : $firstName
";

# Now Set first name using helper function.
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName
";

当我们执行上面的程序,它产生以下结果 -

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
Before Setting First Name is : Mohammad
Before Setting First Name is : Mohd.

方法覆盖

子类Employee继承父类Person中的所有方法。但是,如果你想覆盖你的小孩类中的这些方法,那么你可以通过自己的实现来实现。您可以在子类中添加其他功能,也可以在其父类中添加或修改现有方法的功能。可以这样做:修改Employee.pm文件。

#!/usr/bin/perl

package Employee;
use Person;
use strict;
our @ISA = qw(Person);    # inherits from Person

# Override constructor
sub new {
   my ($class) = @_;

   # Call the constructor of the parent class, Person.
   my $self = $class->SUPER::new( $_[1], $_[2], $_[3] );
   # Add few more attributes
   $self->{_id}   = undef;
   $self->{_title} = undef;
   bless $self, $class;
   return $self;
}

# Override helper function
sub getFirstName {
   my( $self ) = @_;
   # This is child class function.
   print "This is child class helper function
";
   return $self->{_firstName};
}

# Add more methods
sub setLastName{
   my ( $self, $lastName ) = @_;
   $self->{_lastName} = $lastName if defined($lastName);
   return $self->{_lastName};
}

sub getLastName {
   my( $self ) = @_;
   return $self->{_lastName};
}

1;

现在我们再次尝试在main.pl文件中使用Employee对象并执行它。

#!/usr/bin/perl

use Employee;

$object = new Employee( "Mohammad", "Saleem", 23234345);
# Get first name which is set using constructor.
$firstName = $object->getFirstName();

print "Before Setting First Name is : $firstName
";

# Now Set first name using helper function.
$object->setFirstName( "Mohd." );

# Now get first name set by helper function.
$firstName = $object->getFirstName();
print "After Setting First Name is : $firstName
";

当我们执行上面的程序,它产生以下结果 -

First Name is Mohammad
Last Name is Saleem
SSN is 23234345
This is child class helper function
Before Setting First Name is : Mohammad
This is child class helper function
After Setting First Name is : Mohd.

默认自动加载

Perl提供了一个您不会用其他编程语言找到的功能:默认子程序。这意味着,如果定义一个名为AUTOLOAD()的函数那么对未定义子例程的任何调用都将自动调用AUTOLOAD()函数。该子程序中缺少子程序的名称可以作为$ AUTOLOAD访问。

默认自动加载功能对于错误处理非常有用。这是一个实现AUTOLOAD的例子,你可以用你自己的方式实现这个功能。

sub AUTOLOAD
{
   my $self = shift;
   my $type = ref ($self) || croak "$self is not an object";
   my $field = $AUTOLOAD;
   $field =~ s/.*://;
   unless (exists $self->{$field})
   {
      croak "$field does not exist in object/class $type";
   }
   if (@_)
   {
      return $self->($name) = shift;
   }
   else
   {
      return $self->($name);
   }
}

破坏者和垃圾收集

如果您之前已经使用面向对象的编程进行了编程,那么您将会意识到需要创建一个析构函数来释放分配给该对象的内存。一旦对象超出范围,Perl会自动为您做这些。

如果你想实现你的析构函数,这应该照顾关闭文件或做一些额外的处理,那么你需要定义一个名为特殊方法的DESTROY在Perl释放分配给它的内存之前,这个方法将被调用在对象上。在所有其他方面,DESTROY方法就像任何其他方法一样,您可以在此方法中实现所需的任何逻辑。

析构函数方法只是一个名为DESTROY的成员函数(子程序),在以下情况下将自动调用:

例如,您可以简单地将以下DESTROY方法放在您的类中 -

package MyClass;
...
sub DESTROY
{
   print "MyClass::DESTROY called
";
}

面向对象的Perl示例

这是另一个很好的例子,它将帮助您了解Perl的面向对象概念。将此源代码放入任何perl文件并执行。

#!/usr/bin/perl

# Following is the implementation of simple Class.
package MyClass;

sub new
{
   print "MyClass::new called
";
   my $type = shift;            # The package/type name
   my $self = {};               # Reference to empty hash
   return bless $self, $type;   
}

sub DESTROY
{
   print "MyClass::DESTROY called
";
}

sub MyMethod
{
   print "MyClass::MyMethod called!
";
}


# Following is the implemnetation of Inheritance.
package MySubClass;

@ISA = qw( MyClass );

sub new
{
   print "MySubClass::new called
";
   my $type = shift;            # The package/type name
   my $self = MyClass->new;     # Reference to empty hash
   return bless $self, $type;  
}

sub DESTROY
{
   print "MySubClass::DESTROY called
";
}

sub MyMethod
{
   my $self = shift;
   $self->SUPER::MyMethod();
   print "   MySubClass::MyMethod called!
";
}

# Here is the main program using above classes.
package main;

print "Invoke MyClass method
";

$myObject = MyClass->new();
$myObject->MyMethod();

print "Invoke MySubClass method
";

$myObject2 = MySubClass->new();
$myObject2->MyMethod();

print "Create a scoped object
";
{
	my $myObject2 = MyClass->new();
}
# Destructor is called automatically here

print "Create and undef an object
";
$myObject3 = MyClass->new();
undef $myObject3;

print "Fall off the end of the script...
";
# Remaining destructors are called automatically here

当我们执行上面的程序,它产生以下结果 -

Invoke MyClass method
MyClass::new called
MyClass::MyMethod called!
Invoke MySubClass method
MySubClass::new called
MyClass::new called
MyClass::MyMethod called!
   MySubClass::MyMethod called!
Create a scoped object
MyClass::new called
MyClass::DESTROY called
Create and undef an object
MyClass::new called
MyClass::DESTROY called
Fall off the end of the script...
MyClass::DESTROY called
MySubClass::DESTROY called

Perl - 数据库访问

本章教你如何访问Perl脚本中的数据库。从Perl 5开始,使用DBI模块编写数据库应用变得非常容易DBI代表Perl 数据库独立接口,这意味着DBI在Perl代码和底层数据库之间提供了一个抽象层,可以很容易地切换数据库的实现。

DBI是用于Perl编程语言的数据库访问模块。它提供了一组方法,变量和约定,提供一致的数据库接口,与使用的实际数据库无关。

DBI应用程序的体系结构

DBI独立于后端中可用的任何数据库。您是否可以使用DBI,无论您是使用Oracle,MySQL还是Informix等。从以下架构图中可以清楚看出。

Perl数据库模块DBI架构

这里DBI负责通过API(即应用程序编程接口)获取所有SQL命令,并将其发送到相应的驱动程序以进行实际执行。最后,DBI负责从驱动程序中获取结果,并将其发回给被叫的scritp。

符号和公约

在本章节中,将使用以下符号,建议您也应遵循相同的约定。

  $dsn    Database source name
  $dbh    Database handle object
  $sth    Statement handle object
  $h      Any of the handle types above ($dbh, $sth, or $drh)
  $rc     General Return Code  (boolean: true=ok, false=error)
  $rv     General Return Value (typically an integer)
  @ary    List of values returned from the database.
  $rows   Number of rows processed (if available, else -1)
  $fh     A filehandle
  undef   NULL values are represented by undefined values in Perl
  \%attr  Reference to a hash of attribute values passed to methods

数据库连接

假设我们要使用MySQL数据库。连接数据库之前,请确保以下内容。如果您不了解如何在MySQL数据库中创建数据库和表,您可以帮助我们的MySQL教程。

以下是连接MySQL数据库“TESTDB”的示例 -

#!/usr/bin/perl

use DBI
use strict;

my $driver = "mysql"; 
my $database = "TESTDB";
my $dsn = "DBI:$driver:database = $database";
my $userid = "testuser";
my $password = "test123";

my $dbh = DBI->connect($dsn, $userid, $password ) or die $DBI::errstr;

如果使用数据源建立连接,则会返回数据库句柄并将其保存到$ dbh以供进一步使用,否则$ dbh设置为undef值,$ DBI :: errstr返回错误字符string。

插入操作

当您要在表中创建一些记录时,需要执行INSERT操作。这里我们使用表TEST_TABLE创建我们的记录。所以一旦建立了数据库连接,我们就可以在TEST_TABLE中创建记录了。以下是将单个记录创建到TEST_TABLE中的过程。您可以使用相同的概念创建与您喜欢的记录一样多的记录。

记录创建需要以下步骤:

my $sth = $dbh->prepare("INSERT INTO TEST_TABLE
                       (FIRST_NAME, LAST_NAME, SEX, AGE, INCOME )
                         values
                       ("john", "poul", "M", 30, 13000)");
$sth->execute() or die $DBI::errstr;
$sth->finish();
$dbh->commit or die $DBI::errstr;

使用绑定值

可能会提前输入要输入的值的情况。所以你可以使用绑定变量,它将在运行时获取所需的值。Perl DBI模块使用问号代替实际值,然后实际值在运行时通过execute()API传递。以下是这个例子 -

my $first_name = "john";
my $last_name = "poul";
my $sex = "M";
my $income = 13000;
my $age = 30;
my $sth = $dbh->prepare("INSERT INTO TEST_TABLE
                        (FIRST_NAME, LAST_NAME, SEX, AGE, INCOME )
                          values
                        (?,?,?,?)");
$sth->execute($first_name,$last_name,$sex, $age, $income) 
          or die $DBI::errstr;
$sth->finish();
$dbh->commit or die $DBI::errstr;

阅读操作

任何数据库上的READ操作意味着从数据库中获取一些有用的信息,即来自一个或多个表的一个或多个记录。所以一旦建立了数据库连接,我们就可以对这个数据库进行查询了。以下是查询具有AGE大于20的所有记录的过程。这将需要四个步骤 -

my $sth = $dbh->prepare("SELECT FIRST_NAME, LAST_NAME
                        FROM TEST_TABLE 
                        WHERE AGE > 20");
$sth->execute() or die $DBI::errstr;
print "Number of rows found :" + $sth->rows;
while (my @row = $sth->fetchrow_array()) {
   my ($first_name, $last_name ) = @row;
   print "First Name = $first_name, Last Name = $last_name
";
}
$sth->finish();

使用绑定值

可能是事先未提供条件的情况。所以你可以使用绑定变量,这将在运行时获取所需的值。Perl DBI模块使用问号代替实际值,然后实际值在运行时通过execute()API传递。以下是这个例子 -

$age = 20;
my $sth = $dbh->prepare("SELECT FIRST_NAME, LAST_NAME
                        FROM TEST_TABLE
                        WHERE AGE > ?");
$sth->execute( $age ) or die $DBI::errstr;
print "Number of rows found :" + $sth->rows;
while (my @row = $sth->fetchrow_array()) {
   my ($first_name, $last_name ) = @row;
   print "First Name = $first_name, Last Name = $last_name
";
}
$sth->finish();

更新操作

UPDATE对任何数据库的操作意味着更新数据库表中已有的一个或多个记录。以下是将SEX的所有记录更新为“M”的过程。在这里,我们将把所有男性的年龄增加一年。这将需要三个步骤 -

my $sth = $dbh->prepare("UPDATE TEST_TABLE
                        SET   AGE = AGE + 1 
                        WHERE SEX = "M"");
$sth->execute() or die $DBI::errstr;
print "Number of rows updated :" + $sth->rows;
$sth->finish();
$dbh->commit or die $DBI::errstr;

使用绑定值

可能是事先未提供条件的情况。所以你可以使用绑定变量,这将在运行时获取所需的值。Perl DBI模块使用问号代替实际值,然后实际值在运行时通过execute()API传递。以下是这个例子 -

$sex = "M";
my $sth = $dbh->prepare("UPDATE TEST_TABLE
                        SET   AGE = AGE + 1
                        WHERE SEX = ?");
$sth->execute("$sex") or die $DBI::errstr;
print "Number of rows updated :" + $sth->rows;
$sth->finish();
$dbh->commit or die $DBI::errstr;

在某些情况下,您需要设置一个值,该值不提前给出,因此可以使用绑定值如下。在这个例子中,所有男性的收入将设置为10000。

$sex = "M";
$income = 10000;
my $sth = $dbh->prepare("UPDATE TEST_TABLE
                        SET   INCOME = ?
                        WHERE SEX = ?");
$sth->execute( $income, "$sex") or die $DBI::errstr;
print "Number of rows updated :" + $sth->rows;
$sth->finish();

删除操作

当您要从数据库中删除一些记录时,需要执行DELETE操作。以下是从TEST_TABLE中删除AGE等于30的所有记录的过程。此操作将执行以下步骤。

$age = 30;
my $sth = $dbh->prepare("DELETE FROM TEST_TABLE
                         WHERE AGE = ?");
$sth->execute( $age ) or die $DBI::errstr;
print "Number of rows deleted :" + $sth->rows;
$sth->finish();
$dbh->commit or die $DBI::errstr;

使用do语句

如果您正在执行UPDATE,INSERT或DELETE,则不会从数据库返回数据,因此执行此操作有一个快捷方式。您可以使用do语句执行任何命令,如下所示。

$dbh->do("DELETE FROM TEST_TABLE WHERE age =30");

这样做,如果它未能返回,如果它成功了真值和假值。实际上,如果成功,它返回受影响的行数。在该示例中,它将返回实际删除的行数。

COMMIT操作

提交是给数据库提供绿色信号以完成更改的操作,并且在此操作之后,没有更改可以恢复到其信号位置。

这是一个简单的例子来调用commit API。

$dbh->commit or die $dbh->errstr;

ROLLBACK操作

如果您对所有更改不满意,或者在任何操作之间遇到错误,您可以将这些更改还原以使用回滚 API。

这是一个简单的例子来调用回滚 API。

$dbh->rollback or die $dbh->errstr;

开始事物

许多数据库支持事物。这意味着您可以进行一大堆查询,以修改数据库,但实际上没有任何更改。那么最后,你发出特殊的SQL查询COMMIT,所有的更改都是同时进行的。或者,您可以发出查询ROLLBACK,在这种情况下,所有更改都将被丢弃,数据库保持不变。

Perl DBI模块提供了begin_work API,它允许事物(通过关闭AutoCommit)直到下次调用提交或回滚。在下一次提交或回滚后,AutoCommit将自动重新打开。

$rc  = $dbh->begin_work  or die $dbh->errstr;

自动提交选项

如果您的事物很简单,您可以节省自己发出大量提交的麻烦。进行连接呼叫时,您可以指定一个AutoCommit选项,该选项将在每次成功查询后执行自动提交操作。这就是它的样子 -

my $dbh = DBI->connect($dsn, $userid, $password,
              {AutoCommit => 1}) 
              or die $DBI::errstr;

这里AutoCommit可以取值1或0,其中1表示AutoCommit打开,0表示AutoCommit关闭。

自动错误处理

进行连接呼叫时,您可以指定一个自动处理错误的RaiseErrors选项。发生错误时,DBI会中止您的程序,而不是返回故障代码。如果你想要的是中止错误的程序,这可以很方便。这就是它的样子 -

my $dbh = DBI->connect($dsn, $userid, $password,
              {RaiseError => 1})
              or die $DBI::errstr;

这里RaiseError可以取值1或0。

断开数据库

要断开数据库连接,请使用disconnect API,如下所示:

$rc = $dbh->disconnect  or warn $dbh->errstr;

断开连接方法的事务行为是不确定的。某些数据库系统(如Oracle和Ingres)将自动提交任何未完成的更改,但其他数据库系统(如Informix)将会回滚任何未完成的更改。不使用AutoCommit的应用程序应在调用断开连接之前明确地调用commit或rollback。

使用NULL值

未定义的值或undef用于指示NULL值。您可以使用NULL值插入和更新列,而非NULL值。这些示例使用NULL值插入和更新列年龄 -

$sth = $dbh->prepare(qq{
       INSERT INTO TEST_TABLE (FIRST_NAME, AGE) VALUES (?, ?)
       });
 $sth->execute("Joe", undef);

这里使用qq {}返回引用的字符string来准备 API。但是,在WHERE子句中尝试使用NULL值时,必须小心。考虑 -

SELECT FIRST_NAME FROM TEST_TABLE WHERE age = ?

将undef(NULL)绑定到占位符将不会选择具有NULL时间的行!至少对于符合SQL标准的数据库引擎。请参考数据库引擎或任何SQL书籍的SQL手册,原因如下。要显式地选择NULL,你必须说“WHERE age IS NULL”。

一个常见的问题是使代码片段在运行时处理可以被定义的值或undef(非NULL或NULL)。一种简单的技术是根据需要准备适当的语句,并将占位符替换为非空案例 -

$sql_clause = defined $age? "age = ?" : "age IS NULL";
$sth = $dbh->prepare(qq{
       SELECT FIRST_NAME FROM TEST_TABLE WHERE $sql_clause
       });
$sth->execute(defined $age ? $age : ());

一些其他DBI函数

available_drivers

@ary = DBI->available_drivers;
@ary = DBI->available_drivers($quiet);

通过@INC中的目录搜索DBD :: *模块来返回所有可用驱动程序的列表。默认情况下,如果某些驱动程序在较早的目录中被同名的其他驱动程序隐藏,则会发出警告。传递一个真正的价值$ quiet将阻止警告。

installed_drivers

%drivers = DBI->installed_drivers();

返回驱动程序名称和驱动程序句柄对的列表,将所有驱动程序安装到(加载)到当前进程。驱动程序名称不包含“DBD ::”前缀。

数据源

@ary = DBI->data_sources($driver);

返回通过命名驱动程序可用的数据源(数据库)列表。如果$ driver为空或undef,则使用DBI_DRIVER环境变量的值。

引用

$sql = $dbh->quote($value);
$sql = $dbh->quote($value, $data_type);

引用字符string字面值作为SQL语句中的文字值,通过转义字符string中包含的任何特殊字符(如引号)并添加所需类型的外部引号。

$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
                $dbh->quote("Don"t");

对于大多数数据库类型,报价将返回“不要”(包括外部引号)。它对于quote()方法返回一个计算到所需字符string的SQL表达式是有效的。例如 -

$quoted = $dbh->quote("one
twothree")

may produce results which will be equivalent to

CONCAT("one", CHAR(12), "two", CHAR(0), "three")

所有手柄常用的方法

$rv = $h->err;
or
$rv = $DBI::err
or
$rv = $h->err

从最后一个驱动程序方法返回本机数据库引擎的错误代码。代码通常是一个整数,但你不应该假设。这相当于$ DBI :: err或$ h-> err。

错误

$str = $h->errstr;
or
$str = $DBI::errstr
or
$str = $h->errstr

从最后一个调用的DBI方法返回本机数据库引擎的错误消息。这与上述“错误”方法具有相同的寿命问题。这相当于$ DBI :: errstr或$ h-> errstr。

$rv = $h->rows;
or
$rv = $DBI::rows

这将返回先前SQL语句影响的行数,并等效于$ DBI :: rows。

跟踪

$h->trace($trace_settings);

DBI运行一个非常有用的功能来生成运行时跟踪信息,它在做什么,当您尝试跟踪您的DBI程序中的奇怪问题时,这可能是一个巨大的节省时间。您可以使用不同的值来设置跟踪级别。这些值在0到4之间。值0表示禁用跟踪,4表示生成完整的跟踪。

内部声明被禁止

强烈建议不要使用内插语句,如下所示:

while ($first_name = <>) {
   my $sth = $dbh->prepare("SELECT * 
                          FROM TEST_TABLE 
                          WHERE FIRST_NAME = "$first_name"");
   $sth->execute();
   # and so on ...
}

因此,不要使用interpolated语句,而是使用bind值来准备动态SQL语句。

Perl - CGI编程

什么是CGI?

网页浏览

要了解CGI的概念,请看看当我们点击网页上可用的超级链接来浏览特定网页或网址时会发生什么。

然而,可以以这样的方式设置HTTP服务器,使得每当某个目录中的文件被请求时,文件不被发回; 而是作为一个程序执行,无论程序如何输出,都会发送回浏览器进行显示。这可以通过使用Web服务器中可用的特殊功能来实现,称为公共网关接口或CGI,由服务器执行以产生最终结果的这些程序称为CGI脚本。这些CGI程序可以是PERL脚本,Shell脚本,C或C ++程序等。

CGI架构图

CGI架构

Web服务器支持和配置

在进行CGI编程之前,请确保您的Web服务器支持CGI功能,并配置为处理CGI程序。要由Web服务器执行的所有CGI程序都保存在预配置的目录中。该目录被称为CGI目录,按照惯例将其命名为/ cgi-bin。按照惯例Perl CGI文件将扩展为.cgi

第一个CGI计划

这是一个链接到一个名为hello.cgi的CGI脚本的简单链接该文件已保存在/ cgi-bin /目录中,具有以下内容。在运行CGI程序之前,请确保使用chmod 755 hello.cgi UNIX命令更改文件模式

#!/usr/bin/perl

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Hello Word - First CGI Program</title>";
print "</head>";
print "<body>";
print "<h2>Hello Word! This is my first CGI program</h2>";
print "</body>";
print "</html>";

1;

现在,如果您单击hello.cgi链接,则请求访问在/ cgi-bin目录中搜索hello.cgi的Web服务器,执行并生成任何结果,Web服务器将该结果发送回Web浏览器,如下所示 -

Hello Word! This is my first CGI program

这个hello.cgi脚本是一个简单的Perl脚本,它将其输出写入STDOUT文件,即屏幕。有一个重要的和额外的功能可用的第一行要打印Content-type:text / html r n r n该行被发送回浏览器并指定要在浏览器屏幕上显示的内容类型。现在您必须承担CGI的基本概念,您可以使用Perl编写许多复杂的CGI程序。该脚本还可以与任何其他exertnal系统交互,以便交换数据库,Web服务或任何其他复杂接口等信息。

了解HTTP标头

第一行Content-type:text / html r n r n是HTTP头的一部分,它被发送到浏览器,以便浏览器可以从服务器端了解传入的内容。所有HTTP标头将采用以下形式 -

HTTP Field Name: Field Content

例如 -

Content-type:text/html


还有几个其他重要的HTTP标头,您将在CGI编程中频繁使用。


没有 标题与说明
1。 Content-type:String

一个MIME字符string,定义正在返回的内容的格式。示例是Content-type:text / html

2。 到期日期字符string

信息无效的日期。浏览器应该使用它来决定页面何时刷新。有效的日期字符string的格式应为1998年1月01日12:00:00 GMT。

3。 位置:URL字符string

应该返回的URL而不是请求的URL。您可以使用此文件将请求重定向到任何其他位置。

4。 最后修改:字符string

上次修改文件的日期。

5。 Content-length:String

正在返回的数据的长度(以字节为单位)。浏览器使用此值来报告文件的估计下载时间。

6。 Set-Cookie:String

设置通过字符string传递的cookie

CGI环境变量

所有CGI程序都可以访问以下环境变量。这些变量在编写任何CGI程序时起着重要的作用。

没有 变量名称和描述
1。 内容类型

内容的数据类型。当客户端将附件内容发送到服务器时使用。例如文件上传等

2。 CONTENT_LENGTH

查询信息的长度。它仅适用于POST请求

3。 HTTP_COOKIE

以键和值对的形式返回设置的Cookie。

4。 HTTP_USER_AGENT

User-Agent请求头字段包含有关发起请求的用户代理的信息。它的网页浏览器的名称。

5。 PATH_INFO

CGI脚本的路径。

6。 QUERY_STRING

使用GET方法请求发送的URL编码信息。

7。 REMOTE_ADDR

发出请求的远程主机的IP地址。这对于日志记录或认证目的有用。

8。 远程主机

发出请求的主机的完全限定名称。如果此信息不可用,则REMOTE_ADDR可用于获取IR地址。

9。 REQUEST_METHOD

用于提出请求的方法。最常见的方法是GET和POST。

10。 SCRIPT_FILENAME

CGI脚本的完整路径。

11。 SCRIPT_NAME

CGI脚本的名称。

12。 服务器名称

服务器的主机名或IP地址。

13。 SERVER_SOFTWARE

服务器正在运行的软件的名称和版本。

这是一个小型CGI程序,用于列出Web服务器支持的所有CGI变量。点击此链接查看结果获取环境


#!/usr/bin/perl

print "Content-type: text/html

";
print "<font size=+1>Environment</font>
";
foreach (sort keys %ENV)
{
  print "<b>$_</b>: $ENV{$_}<br>
";
}

1;

提起“文件下载”对话框?

有时希望给用户点击链接的选项,它将弹出一个“文件下载”对话框给用户,而不是显示实际的内容。这很简单,将通过HTTP头来实现。

这个HTTP头将不同于上一节中提到的头。例如,如果要使一个FileName文件从一个给定的链接下载,那么它的语法将如下 -

#!/usr/bin/perl

# HTTP Header
print "Content-Type:application/octet-stream; name = "FileName"
";
print "Content-Disposition: attachment; filename = "FileName"

";

# Actual File Content will go hear.
open( FILE, "<FileName" );
while(read(FILE, $buffer, 100) )
{
   print("$buffer");
}

GET和POST方法

当您需要将一些信息从浏览器传递到Web服务器,并最终到您的CGI程序处理您的请求时,您必须遇到许多情况。最常见的浏览器使用两种方法将此信息传递给Web服务器。这些方法是GET方法和POST方法。我们逐一检查一下。

使用GET方法传递信息

GET方法发送附加到页面URL本身的编码用户信息。页面和编码信息由?字符如下 -

http://www.test.com/cgi-bin/hello.cgi?key1=value1&key2=value2

GET方法是将信息从浏览器传递到Web服务器的defualt方法,它产生一个长字符string,出现在浏览器的Location:框中。如果您有密码或其他敏感信息传递给服务器,则不应使用GET方法。GET方法具有大小限制:请求字符string中只能传递1024个字符。

该信息使用QUERY_STRING标头传递,并且可以通过您可以在CGI程序中解析和使用的QUERY_STRING环境变量在CGI程序中访问。

您可以通过简单地将键值和值对连接到任何URL来传递信息,或者您可以使用HTML <FORM>标签来使用GET方法传递信息。

简单的URL示例:获取方法

这是一个简单的URL,它将使用GET方法将两个值传递给hello_get.cgi程序。

http://www.tutorialspoint.com/cgi-bin/hello_get.cgi?first_name=ZARA&last_name=ALI

以下是hello_get.cgi脚本来处理由Web浏览器给出的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{"REQUEST_METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "GET")
{
   $buffer = $ENV{"QUERY_STRING"};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$first_name = $FORM{first_name};
$last_name  = $FORM{last_name};

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Hello - Second CGI Program</title>";
print "</head>";
print "<body>";
print "<h2>Hello $first_name $last_name - Second CGI Program</h2>";
print "</body>";
print "</html>";

1;

简单的FORM示例:GET方法

这是一个简单的例子,它使用HTML FORM和提交按钮传递两个值。我们将使用相同的CGI脚本hello_get.cgi来处理这个输入。

<FORM action = "/cgi-bin/hello_get.cgi" method = "GET">
First Name: <input type = "text" name = "first_name">  <br>

Last Name: <input type = "text" name = "last_name">
<input type = "submit" value = "Submit">
</FORM>

这是上述表单编码的实际输出。现在可以输入“First”和“Last Name”,然后单击“Submit”按钮查看结果。

名字:

姓:

使用POST方法传递信息

将信息传递给CGI程序的更可靠的方法是POST方法。这将以与GET方法完全相同的方式打包信息,而不是将其作为文本字符string发送在URL中,它作为HTTP标头的一部分将其作为单独的消息发送。Web服务器以标准输入的形式向CGI脚本提供此消息。

以下是修改的hello_post.cgi脚本来处理Web浏览器给出的输入。此脚本将处理GET以及POST方法。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{"REQUEST_METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "POST")
{
   read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});
}else {
   $buffer = $ENV{"QUERY_STRING"};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$first_name = $FORM{first_name};
$last_name  = $FORM{last_name};

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Hello - Second CGI Program</title>";
print "</head>";
print "<body>";
print "<h2>Hello $first_name $last_name - Second CGI Program</h2>";
print "</body>";
print "</html>";

1;

让我们再次采取与上述相同的考试,它通过使用HTML FORM和提交按钮传递两个值。我们将使用CGI脚本hello_post.cgi来处理这个输入。

<FORM action = "/cgi-bin/hello_post.cgi" method = "POST">
First Name: <input type = "text" name = "first_name">  <br>

Last Name: <input type = "text" name = "last_name">

<input type = "submit" value = "Submit">
</FORM>

这是上述表单编码的实际输出,您输入First和Last Name,然后单击Submit按钮查看结果。

名字:

姓:

将复选框数据传递给CGI程序

当需要多个选项时,使用复选框。这是一个具有两个复选框的表单的示例HTML代码。

<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">
<input type = "checkbox" name = "maths" value = "on"> Maths
<input type = "checkbox" name = "physics" value = "on"> Physics
<input type = "submit" value = "Select Subject">
</form>

此代码的结果如下:

数学 物理

下面是checkbox.cgi脚本来处理由web浏览器给出的单选按钮的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{"REQUEST_METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "POST")
{
   read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});
}else {
   $buffer = $ENV{"QUERY_STRING"};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
if( $FORM{maths} ){
   $maths_flag ="ON";
}else{
   $maths_flag ="OFF";
}
if( $FORM{physics} ){
   $physics_flag ="ON";
}else{
   $physics_flag ="OFF";
}

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Checkbox - Third CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> CheckBox Maths is : $maths_flag</h2>";
print "<h2> CheckBox Physics is : $physics_flag</h2>";
print "</body>";
print "</html>";

1;

将无线电按钮数据传递给CGI程序

当需要选择一个选项时,使用单选按钮。这是一个表单的HTML代码示例,带有两个单选按钮 -

<form action = "/cgi-bin/radiobutton.cgi" method = "POST" target = "_blank">
<input type = "radio" name = "subject" value = "maths"> Maths
<input type = "radio" name = "subject" value = "physics"> Physics
<input type = "submit" value = "Select Subject">
</form>

此代码的结果如下:

数学 物理

下面是radiobutton.cgi脚本来处理由web浏览器给出的单选按钮的输入。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{"REQUEST_METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "POST")
{
   read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});
}else {
   $buffer = $ENV{"QUERY_STRING"};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$subject = $FORM{subject};

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Radio - Fourth CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> Selected Subject is $subject</h2>";
print "</body>";
print "</html>";

1;

将文本区域数据传递给CGI程序

当多行文本必须传递给CGI程序时,将使用textarea元素。以下是具有TEXTAREA框的表单HTML代码示例 -

<form action = "/cgi-bin/textarea.cgi" method = "POST" target = "_blank">
<textarea name = "textcontent" cols = 40 rows = 4>
Type your text here...
</textarea>
<input type = "submit" value = "Submit">
</form>

此代码的结果如下:

以下是用于处理Web浏览器给出的输入textarea.cgi脚本。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{"REQUEST_METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "POST")
{
   read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});
}else {
   $buffer = $ENV{"QUERY_STRING"};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$text_content = $FORM{textcontent};

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> Entered Text Content is $text_content</h2>";
print "</body>";
print "</html>";

1;

将下拉框数据传递给CGI程序

当我们有很多可用选项时,会使用一个下拉框,但只会选择一个或两个。以下是一个带有一个下拉框的表单的HTML代码示例

<form action = "/cgi-bin/dropdown.cgi" method = "POST" target = "_blank">
<select name = "dropdown">
<option value = "Maths" selected>Maths</option>
<option value = "Physics">Physics</option>
</select>
<input type = "submit" value = "Submit">
</form>

此代码的结果如下:

以下是用于处理由Web浏览器给出的输入dropdown.cgi脚本。

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{"REQUEST_METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "POST")
{
   read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});
}else {
   $buffer = $ENV{"QUERY_STRING"};
}
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex($1))/eg;
   $FORM{$name} = $value;
}
$subject = $FORM{dropdown};

print "Content-type:text/html

";
print "<html>";
print "<head>";
print "<title>Dropdown Box - Sixth CGI Program</title>";
print "</head>";
print "<body>";
print "<h2> Selected Subject is $subject</h2>";
print "</body>";
print "</html>";

1;

在CGI中使用Cookie

HTTP协议是无状态协议。但是对于商业网站,需要在不同的页面之间维护会话信息。例如,一个用户注册在跨越许多页面的事务之后结束。但是如何在所有网页上维护用户的会话信息?

在许多情况下,使用Cookie是记住和跟踪更好的访问者体验或站点统计所需的偏好,购买,佣金和其他信息的最有效的方法。

怎么运行的

您的服务器会以Cookie的形式向访问者的浏览器发送一些数据。浏览器可能会接受cookie。如果是这样,它将作为纯文本记录存储在访问者的硬盘上。现在,当访问者到达您网站上的另一个页面时,该cookie可用于检索。检索后,您的服务器会知道/记住所存储的内容。

Cookie是5个可变长度字段的纯文本数据记录 -

设置cookie

将cookies发送到浏览器非常简单。这些cookie将与HTTP头一起发送。假设您要将UserID和Password设置为Cookie。所以这样做会如下 -

#!/usr/bin/perl

print "Set-Cookie:UserID = XYZ;
";
print "Set-Cookie:Password = XYZ123;
";
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT";
";
print "Set-Cookie:Domain = www.tutorialspoint.com;
";
print "Set-Cookie:Path = /perl;
";
print "Content-type:text/html

";
...........Rest of the HTML Content goes here....

这里我们使用Set-Cookie HTTP头来设置cookie。设置Cookie属性(如Expires,Domain和Path)是可选的。重要的是要注意,在发送魔术线“Content-type:text / html r n r n”之前设置了Cookie

检索cookie

检索所有设置的cookie很容易。Cookie存储在CGI环境变量HTTP_COOKIE中,它们将具有以下格式。

key1 = value1;key2 = value2;key3 = value3....

以下是如何检索Cookie的示例。

#!/usr/bin/perl
$rcvd_cookies = $ENV{"HTTP_COOKIE"};
@cookies = split /;/, $rcvd_cookies;
foreach $cookie ( @cookies ){
   ($key, $val) = split(/=/, $cookie); # splits on the first =.
   $key =~ s/^s+//;
   $val =~ s/^s+//;
   $key =~ s/s+$//;
   $val =~ s/s+$//;
   if( $key eq "UserID" ){
      $user_id = $val;
   }elsif($key eq "Password"){
      $password = $val;
   }
}
print "User ID  = $user_id
";
print "Password = $password
";

输出结果如下,如上所述,Cookie在调用检索Cookie脚本之前已设置。

User ID = XYZ
Password = XYZ123

CGI模块和图书馆

您将通过互联网找到许多内置模块,为您提供CGI程序中直接使用的功能。以下是重要的一次。

Perl - 软件包和模块

什么是包?

语句切换当前命名上下文指定的命名空间(符号表)。因此 -

以下是一个文件中包含main和Foo包的示例。这里使用了特殊变量__PACKAGE__来打印包名称。

#!/usr/bin/perl

# This is main package
$i = 1; 
print "Package name : " , __PACKAGE__ , " $i
"; 

package Foo;
# This is Foo package
$i = 10; 
print "Package name : " , __PACKAGE__ , " $i
"; 

package main;
# This is again main package
$i = 100; 
print "Package name : " , __PACKAGE__ , " $i
"; 
print "Package name : " , __PACKAGE__ ,  " $Foo::i
"; 

1;

当执行上述代码时,它产生以下结果 -

Package name : main 1
Package name : Foo 10
Package name : main 100
Package name : main 10

BEGIN和END块

您可以定义任何数量的名为BEGIN和END的代码块,分别充当构造函数和析构函数。

BEGIN { ... }
END { ... }
BEGIN { ... }
END { ... }

以下示例显示其用法 -

#!/usr/bin/perl

package Foo;
print "Begin and Block Demo
";

BEGIN { 
    print "This is BEGIN Block
" 
}

END { 
    print "This is END Block
" 
}

1;

当执行上述代码时,它产生以下结果 -

This is BEGIN Block
Begin and Block Demo
This is END Block

什么是Perl模块?

Perl模块是在库文件中定义的可重用包,其名称与.pm作为扩展名的包名称相同。

名为Foo.pm的 Perl模块文件可能包含这样的语句。

#!/usr/bin/perl

package Foo;
sub bar { 
   print "Hello $_[0]
" 
}

sub blat { 
   print "World $_[0]
" 
}
1;

关于Perl模块的几点重要

需求功能

可以通过调用require函数来加载模块,如下所示:

#!/usr/bin/perl

require Foo;

Foo::bar( "a" );
Foo::blat( "b" );

您必须注意到,子程序名称必须完全符合要求。将子例程blat引入我们自己的命名空间是非常好的,所以我们不必使用Foo :: qualifier。

使用功能

可以通过调用使用函数来加载模块

#!/usr/bin/perl

use Foo;

bar( "a" );
blat( "b" );

请注意,我们没有完全限定包的功能名称。使用功能将出口从给定模块内的几个语句添加一个模块的符号列表。

require Exporter;
@ISA = qw(Exporter);

然后,通过填充名为@EXPORT的列表变量来提供符号列表(标量,列表,散列,子程序等):对于示例 -

package Module;

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(bar blat);

sub bar { print "Hello $_[0]
" }
sub blat { print "World $_[0]
" }
sub splat { print "Not $_[0]
" }  # Not exported!

1;

创建Perl模块树

当您准备好运送您的Perl模块时,有标准的创建Perl模块树的方法。这是使用h2xs实用程序完成的这个实用程序与Perl一起。以下是使用h2xs的语法 -

$h2xs -AX -n  ModuleName

例如,如果您的模块在Person.pm文件可用,则只需发出以下命令 -

$h2xs -AX -n Person

输出结果如下 -

Writing Person/lib/Person.pm
Writing Person/Makefile.PL
Writing Person/README
Writing Person/t/Person.t
Writing Person/Changes
Writing Person/MANIFEST

这是这些选项的描述 -

以上命令在Person目录下创建以下结构。实际结果如上所示。

所以最后,你焦油该目录结构到一个文件Person.tar.gz,您可以出货。您将不得不使用正确的说明更新README文件。您还可以在t目录中提供一些测试示例文件。

安装Perl模块

以tar.gz文件格式下载Perl模块。使用以下顺序安装任何Person.tar.gz文件下载的Perl Module Person.pm

tar xvfz Person.tar.gz
cd Person
perl Makefile.PL
make
make install

Perl解释器具有搜索模块的目录列表(全局数组@INC)。

Perl - 流程管理

您可以使用Perl以各种方式根据您的要求创建新的进程。本教程将列出创建和管理Perl进程的一些重要和最常用的方法。

背板操作器

执行任何Unix命令的最简单的方法是使用背景操作符。您只需将命令放在反驳操作符中,这将导致命令的执行并返回其结果,可以如下存储:

#!/usr/bin/perl

@files = `ls -l`;

foreach $file (@files){
   print $file;
}

1;

当执行上述代码时,它会列出当前目录中可用的所有文件和目录 -

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

system()函数

您还可以使用system()函数来执行任何Unix命令,其输出将转到perl脚本的输出。默认情况下,它是屏幕,即STDOUT,但您可以使用重定向操作符> - 将其重定向到任何文件 -

#!/usr/bin/perl

system( "ls -l")

1;

当执行上述代码时,它会列出当前目录中可用的所有文件和目录 -

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

当您的命令包含shell环境变量(如$ PATH或$ HOME)时,请小心。尝试以下三种情况 -

#!/usr/bin/perl

$PATH = "I am Perl Variable";

system("echo $PATH");  # Treats $PATH as shell variable
system("echo $PATH");  # Treats $PATH as Perl variable
system("echo $PATH"); # Escaping $ works.

1;

当执行上面的代码时,它会根据shell变量$ PATH中设置的内容生成以下结果。

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
I am Perl Variable
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin

fork()函数

Perl提供了一个对应于同名的Unix系统调用的fork()函数。在fork()系统调用可用的大多数类Unix平台上,Perl的fork()只是调用它。在诸如Windows(其中fork())系统调用不可用的某些平台上,可以创建Perl以在解释器级别模拟fork()。

fork()函数用于克隆当前进程。此调用创建一个在同一点运行相同程序的新进程。它将子进程pid返回给父进程,0返回给子进程,如果fork不成功则返回undef。

您可以在进程中使用exec()函数来启动所请求的可执行文件,这些可执行文件将在单独的进程区域中执行,而exec()将等待它在退出之前以与该进程相同的退出状态来完成。

#!/usr/bin/perl

if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
}elsif ($pid == 0) {
   print "Printed by child process
";
   exec("date") || die "can"t exec date: $!";
  
} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process
";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret
";

}

1;

当执行上述代码时,它产生以下结果 -

Printed by parent process
Printed by child process
Tue Sep 17 15:41:08 CDT 2013
Completed process id: 17777

等待()waitpid函数()可以为()由叉返回伪进程ID被传递。这些调用将正确地等待伪程序的终止并返回其状态。如果你没有等待你的孩子使用waitpid()函数,你会积累僵尸。在Unix系统上,可以通过将$ SIG {CHLD}设置为“IGNORE”来避免这一点,如下所示:

#!/usr/bin/perl

local $SIG{CHLD} = "IGNORE";
 
if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
}elsif ($pid == 0) {
   print "Printed by child process
";
   exec("date") || die "can"t exec date: $!";
  
} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process
";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret
";

}

1;

当执行上述代码时,它产生以下结果 -

Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1

kill()函数

Perl kill("KILL",(进程列表))功能可以通过传递fork()返回的ID来终止伪进程。

请注意,在伪进程()上使用kill("KILL",(Process List))通常可能会导致内存泄漏,因为实现伪进程的线程没有机会清理其资源。

您可以使用kill()函数将任何其他信号发送到目标进程,例如下面将发送SIGINT到进程ID 104和102 -

#!/usr/bin/perl

kill("INT", 104, 102);
 
1;

Perl - 嵌入式文档

您可以在您的Perl模块和脚本中嵌入Pod(Plain Old Text)文档。以下是在Perl代码中使用嵌入式文档的规则 -

开始使用一个空行,a = head1命令开始你的文档,并用a = cut结束

Perl将忽略您在代码中输入的Pod文本。以下是在Perl代码中使用嵌入式文档的简单示例 -

#!/usr/bin/perl

print "Hello, World
";

=head1 Hello, World Example
This example demonstrate very basic syntax of Perl.
=cut

print "Hello, Universe
";

当执行上述代码时,它产生以下结果 -

Hello, World
Hello, Universe

如果要将Pod放在文件末尾,并且使用__END__或__DATA__切割标记,请确保在第一个Pod命令之前放置一个空行,如下所示,否则没有空行= head1,许多翻译者将不会将= head1识别为启动Pod块。

#!/usr/bin/perl

print "Hello, World
";

while(<DATA>){
  print $_;
}

__END__

=head1 Hello, World Example
This example demonstrate very basic syntax of Perl.
print "Hello, Universe
";

当执行上述代码时,它产生以下结果 -

Hello, World

=head1 Hello, World Example
This example demonstrate very basic syntax of Perl.
print "Hello, Universe
";

让我们再来一个例子来看同样的代码,而不用读DATA部分 -

#!/usr/bin/perl

print "Hello, World
";

__END__

=head1 Hello, World Example
This example demonstrate very basic syntax of Perl.
print "Hello, Universe
";

当执行上述代码时,它产生以下结果 -

Hello, World

什么是POD?

Pod是用于为Perl,Perl程序和Perl模块编写文档的简单易用的标记语言。有各种翻译可用于将Pod转换为各种格式,如纯文本,HTML,手册页等。Pod标记由三种基本类型的段落组成:

=pod
=head1 Heading Text
=head2 Heading Text
=head3 Heading Text
=head4 Heading Text
=over indentlevel
=item stuff
=back
=begin format
=end format
=for format text...
=encoding type
=cut

POD示例

考虑以下POD -

=head1 SYNOPSIS
Copyright 2005 [TUTORIALSOPOINT].
=cut

您可以使用Linux上可用的pod2html实用程序将上述POD转换为HTML,从而产生以下结果 -

版权所有2005 [TUTORIALSOPOINT]。

接下来,考虑以下示例 -

=head2 An Example List

=over 4
=item * This is a bulleted list.
=item * Here"s another item.
=back
=begin html
<p>
Here"s some embedded HTML.  In this block I can
include images, apply <span style="color: green">
styles</span>, or do anything else I can do with
HTML.  pod parsers that aren"t outputting HTML will
completely ignore it.
</p>

=end html

当您使用pod2html将上述POD转换为HTML时,输出结果如下-

An Example List
   This is a bulleted list.
   Here"s another item.
Here"s some embedded HTML. In this block I can include images, apply 
styles, or do anything else I can do with HTML. pod parsers that aren"t 
outputting HTML will completely ignore it.

Perl - 函数参考

以下是标准Perl支持的所有重要功能的列表。