在命令行输入
perldoc perlintro
输出
以下是文档内容
什么是Perl
Perl是一种通用编程语言,最初是为文本处理而开发的,现在用于包括系统管理、Web开发、网络编程、GUI开发等在内的广泛任务。
该语言旨在实用(易于使用、高效、完整)而非美观(小巧、优雅、简约)。其主要特点是易于使用,支持过程式和面向对象(OO)编程,具有强大的内置文本处理支持,并且拥有世界上最令人印象深刻的第三方模块集合之一。
Perl在perl、perlfaq1等不同地方有不同的定义,毫无疑问还有其他定义。
运行Perl程序
要从Unix命令行运行Perl程序:
perl programname.pl
或者,将以下内容作为脚本的第一行:
#!/usr/bin/env perl
然后运行脚本为/path/to/script.pl
。当然,它需要先可执行,所以在Unix下使用“chmod 755 script.pl”。
(这个启动行假设您有env程序(即设置了环境变量)。您也可以直接将Perl可执行文件的路径放在里面,例如“#!/usr/bin/perl”。)
有关更多信息,包括Windows和Mac OS等其他平台的说明,请阅读perlrun。
安全网
Perl默认是非常宽容的。为了使其更加健壮,建议以以下两行代码开始每个程序:
#!/usr/bin/perl
use strict;
use warnings;
这两行额外的代码请求Perl捕获代码中的各种常见问题。它们检查不同的事情,因此您需要同时使用它们。被“use strict;”捕获的潜在问题将导致代码在遇到时立即停止,而“use warnings;”只会给出警告(类似于命令行开关-w),并让代码运行。要了解更多关于它们检查的内容,请查看strict和warnings的相应手册页。
基本语法概述
Perl脚本或程序由一个或多个语句组成。这些语句简单地按顺序写在脚本中。没有必要有一个“main()”函数或类似的东西。
分号
Perl语句以分号结尾
print "Hello, world";
注释 #
注释以井号符号开始,并运行到行尾
# This is a comment
空白
空白是无关紧要的
print
"Hello world"
;
除了在引号字符串内部
# 这将在中间打印一个换行符
print "Hello
world";
双引号/单引号
双引号或单引号可用于包围字面字符串
print "Hello, world";
print 'Hello, world';
然而,只有双引号会“插值”变量和特殊字符,如换行符("\n")
print "Hello, $name\n"; # 正常工作
print 'Hello, $name\n'; # 打印 $name\n 字面值
数字不需要用引号包围
print 42;
括号
您可以根据个人喜好使用括号来表示函数的参数,或者省略它们。它们仅在需要澄清优先级问题时偶尔需要。
print("Hello, world\n");
print "Hello, world\n";
两种形式完全等效
需要括号的情况
解决优先级问题
print 2 + 3; # 输出5(先计算2+3)
print(2) + 3; # 输出2然后计算+3(实际输出24)
执行步骤分解
-
函数调用:
-
print(2)
首先执行,输出数字"2"到标准输出 -
print
函数在成功执行后返回1(表示成功)
-
-
数值相加:
-
表达式变为
1 + 3
(因为print返回1) -
计算结果为4
-
-
最终输出:
-
由于Perl默认会输出最后一个表达式的结果
-
数字4被自动输出,紧跟在之前输出的"2"后面
-
组合起来就是"24"(先输出2,再输出4)
-
有关Perl语法的更详细信息可以在perlsyn中找到。
Perl变量类型
Perl主要有三种变量类型:标量、数组和哈希。
标量 $
标量表示单个值
my $animal = "camel";
my $answer = 42;
标量值可以是字符串、整数或浮点数,Perl会根据需要自动在它们之间进行转换。您不需要预先声明变量类型,但您必须在第一次使用它们时使用“my”关键字进行声明。(这是“use strict;”的要求之一。)
使用方式
有一些名字看起来像标点符号或行噪声的“魔法”标量。这些特殊变量用于各种目的,并在perlvar中进行了文档说明。现在您需要知道的是$_
,它是“默认变量”。它被用作Perl中许多函数的默认参数,并且由某些循环结构隐式设置。
perl复制
print;
# 默认打印 $_
数组 @
数组表示值的列表
my @animals = ("camel", "llama", "owl");
my @numbers = (23, 42, 69);
my @mixed = ("camel", 42, 1.23);
数组是从零开始索引的
在数组中获取元素的方法
print $animals[0]; # 打印 "camel"
print $animals[1]; # 打印 "llama"
特殊变量 $#array 返回
数组最后一个元素的索引:
print $mixed[$#mixed]; # 最后一个元素,打印 1.23
您可能会倾向于使用“$#array + 1
”来告诉您数组中有多少项,不要费心。这是不推荐的老式写法
正确方法:直接在标量上下文中使用 @array
my $count = @array; # 自动转换为元素数量
我们从数组中获取的元素以“$
”开头,因为我们只是从数组中获取单个值;您请求一个标量,您就会得到一个标量。
上下文: 在 Perl 中,同一个表达式在不同上下文中会产生不同的行为
标量上下文: 当 Perl 期望得到一个单个值时,就处于标量上下文
标量上下文场景
my $num = @array; # 赋值给标量变量,@array返回数组个数
if (@array) { ... } # 条件判断
print @array + 5; # 数值运算
my $len = length @array; # 函数参数
数组在标量上下文中的行为
-
返回数组的长度(元素个数)
my @fruits = ('apple', 'banana', 'orange');
my $count = @fruits; # $count 得到值3
列表上下文: 当 Perl 期望得到多个值的列表时,就处于列表上下文
场景
my @copy = @array; # 数组赋值
print @array; # 打印语句
my @sliced = @array[1..3]; # 数组切片
为什么my $num = @array; 是标量上下文, my @copy = @array; 是列表上下文
赋值目标决定上下文
-
当赋值的目标是一个 数组(
@copy
) 或列表时,Perl 会强制右边的表达式(@array
)在 列表上下文 中求值。 -
这意味着
@array
会返回它的 所有元素,而不是像标量上下文那样返回数组的长度
在列表上下文中,@array
展开为它的所有元素
my @array = (1, 2, 3);
my @copy = @array; # @copy 现在是 (1, 2, 3)
数组切片 : 从数组中获取多个值
@animals[0,1]; # 返回 ("camel", "llama");
@animals[0..2]; # 返回 ("camel", "llama", "owl");
@animals[1..$#animals]; # 返回除第一个元素之外的所有元素
您可以对列表执行各种有用操作:
my @sorted = sort @animals;
my @backwards = reverse @numbers;
还有一些特殊的数组,例如@ARGV
(传递给您脚本的命令行参数)和@_
(传递给子程序的参数)。这些在perlvar中有文档说明。
哈希 %
哈希表示一组键/值对:
my %fruit_color = ("apple", "red", "banana", "yellow");
这是一个哈希的初始化, 创建一个哈希 %fruit_color
-
键(key):"apple" → 值(value):"red"
-
键(key):"banana" → 值(value):"yellow"
您可以使用空格和“=>
”运算符来更清晰地排列它们:
my %fruit_color = (
"apple" => "red",
"banana" => "yellow",
);
要获取哈希元素
$fruit_color{"apple"}; # 返回 "red"
您可以使用“keys()
”和“values()
”获取键和值的列表:
my @fruits = keys %fruit_color;
my @colors = values %fruit_color;
-
@fruits
数组将包含哈希的所有键(key):-
可能的结果:
("apple", "banana")
-
注意:
keys
返回的顺序是不确定的,也可能是("banana", "apple")
-
-
@colors
数组将包含哈希的所有值(value):-
可能的结果:
("red", "yellow")
-
顺序与对应的
keys
顺序一致
-
哈希没有特定的内部顺序,尽管您可以对键进行排序并遍历它们。
就像特殊的标量和数组一样,也有特殊的哈希。其中最著名的是%ENV
,它包含环境变量。在perlvar中阅读有关它(和其他特殊变量)的所有信息。
标量、数组和哈希在perldata中有更完整的文档说明。
可以使用引用构建更复杂的数据类型,这允许您在列表和哈希中构建列表和哈希。
引用
引用是一个标量值,可以引用任何其他Perl数据类型。因此,通过将引用存储为数组或哈希元素的值,您可以轻松地在列表和哈希中创建列表和哈希。以下示例显示了使用匿名哈希引用创建的2级哈希结构。
my $variables = {
scalar => { description => "single item", sigil => '%' },
array => { description => "ordered list", sigil => '@' },
hash => { description => "key/value pairs", sigil => '%' }
};
print "Scalars begin with a $variables->{'scalar'}->{'sigil'}\n";
先创建了复杂数据结构>>再进行数据访问
一个嵌套的哈希引用,结构如下:
-
顶级哈希( 最外层的哈希变量 )包含3个键:
scalar
,array
,hash
-
每个键对应的值又是一个哈希引用,包含:
-
description
: 类型描述 -
sigil
: Perl 变量符号
-
引用访问嵌套数据
-
$variables->{'scalar'}
获取 scalar 对应的哈希引用 -
->{'sigil'}
进一步获取该哈希中的 sigil 值 -
最终输出
$
符号(scalar 的 sigil)
执行结果
Scalars begin with a $
关于引用主题的详尽信息可以在perlrefut, perllol, perlref和perldsc中找到。
变量作用域
在前面的部分中,所有示例都使用了语法:
my $var = "value";
实际上“my”并不是必需的;您也可以使用
$var = "value";
然而,上述用法会在程序中创建全局变量,这是不良的编程“my”创建的是词法作用域变量。变量的作用域限定在它们被定义的块中(即一组实践。由大括号包围的语句)。
my $x = "foo"; # 外层作用域变量$x
my $some_condition = 1; # 控制条件
if ($some_condition) {
my $y = "bar"; # 内层作用域变量$y
print $x; # 输出 "foo" (可以访问外层变量)
print $y; # 输出 "bar" (访问当前作用域变量)
}
print $x; # 输出 "foo" (外层变量仍然存在)
print $y; # 输出空 (内层$y已超出作用域)
输出结果
foobarfoo
在Perl脚本顶部使用 "my" 和 "use strict;" 意味着解释器将捕获某些常见的编程错误。例如,在上述示例中,最后的 "print $y" 将导致编译时错误并阻止您运行程序。强烈建议使用 "strict"。
条件和循环结构
Perl具有大多数常见的条件和循环结构。截至Perl 5.10,它甚至有case/switch语句(拼写为 "given"/"when")。有关更多详细信息,请参阅perlsyn中的 "Switch Statements"。
条件可以是任何Perl表达式。请参阅下一部分中的运算符列表,了解有关比较和布尔逻辑运算符的信息,这些运算符通常用于条件语句中。
if 条件 和unless
if
if (条件) {
...
} elsif (其他条件) {
...
} else {
...
}
还有一个否定版本
unless (条件) {
...
}
这被提供为 "if (!*条件*)" 的更易读版本。
请注意,在Perl中,即使块中只有一行代码,也需要使用大括号。然而,有一种更聪明的方法可以使您的单行条件块更像英语
# 传统方式
if ($zippy) {
print "Yow!";
}
# Perl的后置条件方式
print "Yow!" if $zippy;
print "We have no bananas" unless $bananas;
当变量 $zippy
为 真(true) 时,会打印输出字符串 "You!"
;当 $zippy
为 假(false) 时,则什么都不做。
-
当
$bananas
为假时:打印 "We have no bananas" -
当
$bananas
为真时:什么都不做
while条件和untill
while
while (条件) {
...
}
也有一个否定版本,原因和我们有 "unless" 一样
until (条件) {
...
}
您还可以在后置条件中使用 "while"
print "LA LA LA\n" while 1; # 无限循环
for循环
类C风格
for ($i = 0; $i <= $max; $i++) {
...
}
foreach 循环
C 风格的 for 循环在 Perl 中很少需要,因为 Perl 提供了更友好的列表扫描 "foreach" 循环。
foreach
foreach (@array) {
print "This element is $_\n";
}
print $list[$_] foreach 0 .. $max;
# 您不必使用默认的 $_,也可以...
foreach my $key (keys %hash) {
print "The value of $key is $hash{$key}\n";
}
-
第一段代码展示了如何遍历数组并打印每个元素。
-
第二段代码展示了如何使用索引遍历数组并打印元素。
-
第三段代码展示了如何遍历哈希并打印每个键及其对应的值。
"foreach" 关键字实际上是 "for" 关键字的同义词。有关 "Foreach Loops" 的更多信息,请参阅 perlsyn。
有关循环结构(以及本概述中未提及的一些)的更多详细信息,请参阅 perlsyn。
内置运算符和函数
Perl 带有大量内置函数。我们已经看到的一些包括 "print"、"sort" 和 "reverse"。可以通过使用 "perldoc -f *functionname*" 轻松阅读有关任何给定函数的信息。
Perl 运算符在 perlop 中有完整文档,但以下是一些最常见的:
算术运算
-
+
加法 -
-
减法 -
*
乘法 -
/
除法
数值比较
-
==
等于 -
!=
不等于 -
<
小于 -
>
大于 -
<=
小于或等于 -
>=
大于或等于
字符串比较
-
eq
等于 , 即"equal" -
ne
不等于, 即"not equal" -
lt
小于, 即"less than" -
gt
大于, 即 "greater than" -
le
小于或等于, 即 "less than or equal" -
ge
大于或等于, "greater than or equal"
(为什么我们要有单独的数值和字符串比较?因为我们没有特殊的变量类型,Perl需要知道是按数值(例如99小于100)还是按字母顺序(例如100在99之前)进行排序。)
布尔逻辑
-
&&
与 -
||
或 -
!
非
(“与”、“或”和“非”不仅仅是上面表格中运算符的描述。它们也作为运算符直接支持。它们比C风格的运算符更易读,但优先级与“&&”及其相关运算符不同。有关更多详细信息,请参阅perlop。)
杂项
-
=
赋值 -
.
字符串连接 -
x
字符串重复(重复字符串) -
..
范围运算符(创建数字或字符串的列表)
许多运算符可以与 =
结合使用,如下所示:
$a += 1; # 等同于 $a = $a + 1
$a -= 1; # 等同于 $a = $a - 1
$a .= "\n"; # 等同于 $a = $a . "\n";
文件和输入/输出
open()
您可以使用 "open()"
函数打开文件进行输入或输出。它在 perlfunc 和 perlopentut 中有详细文档说明,简而言之:
open(my $in, "<", "input.txt") or die "Can't open input.txt: $!";
open(my $out, ">", "output.txt") or die "Can't open output.txt: $!";
open(my $log, ">>", "my.log") or die "Can't open my.log: $!";
您可以使用 <>
运算符从打开的文件句柄中读取。在标量上下文中,它从文件句柄中读取一行,而在列表上下文中,它读取整个文件,将每一行分配给列表中的一个元素:
my $line = <$in>;
my @lines = <$in>;
一次性读取整个文件称为“slurping”。这可能有用,但也可能是内存消耗大户。大多数文本文件处理可以逐行使用Perl的循环结构完成。
<>
运算符最常在 "while"
循环中看到:
while (<$in>) { # 依次将每一行赋值给 $_
print "Just read in this Line: $_";
}
$_特殊默认变量
被称为 "topic variable"(主题变量)。它是许多 Perl 操作(如循环、正则匹配、打印等)的 隐式操作对象。当某些操作未明确指定变量时,Perl 会自动使用 $_
避免使用 $_的场景
复杂逻辑 当代码嵌套多层时,显式命名变量更清晰
性能敏感场景:直接操作命名变量可能略快(但差异通常微小)。
print
我们已经知道如何使用 "print()"
打印到标准输出。然而,"print()"
也可以接受一个可选的第一个参数,指定要打印到的文件句柄:
print STDERR "This is your final warning.\n";
print $out $record;
print $log $logmessage;
完成文件句柄操作后,您应该 "close()"
它们(尽管说实话,如果您忘记了,Perl会在之后为您清理):
close $in or die "$in: $!";
$! 是一个特殊的内置变量,它代表上一个系统调用的错误号