Skip to content

Perl 语法概览

Perl 的语法从 C、awk、sed 和 shell 脚本等多种语言中汲取灵感。虽然它拥有丰富的历史传承,但现代 Perl 开发强调代码的清晰性和健壮性。本章将指导你学习基本语法,并融入当前的最佳实践。

Perl 程序是从上到下执行的语句序列。循环和子程序 (subroutines) 等控制结构 (control structure) 允许非线性执行。每个简单语句都必须以分号 (;) 结尾。控制结构等复杂语句有自己的终止语法规则(通常是闭合的花括号 })。

Perl 是一种自由格式语言 (free-form language),这意味着空白字符 (whitespace)(空格、制表符、换行符)通常用于分隔标记 (tokens) 和提高可读性,而不是像 Python 那样用于定义结构。然而,一致的格式化对于可维护的代码至关重要。

强烈建议每个 Perl 脚本都以以下行开头:

use strict;
use warnings;

use strict; 为你的代码强制执行更严格的规则,捕获许多常见错误。use warnings; 启用有用的诊断消息。使用这些编译指示 (pragmas) 是现代 Perl 编程的基石。

可以使用 -e 选项直接从命令行执行 Perl 代码。这对于快速测试非常方便:

$ perl -e 'print "Hello, Modern Perl!\n"'

这将输出:

Hello, Modern Perl!

对于在单行命令 (one-liners) 中启用像 say 或 strictures 这样的特性 (features),可以使用 -E(它隐含了对启用特性的 use feature)或 -M 来加载模块 (modules):

$ perl -E 'say "Hello using say!"' # say 会自动添加换行
$ perl -Mstrict -e 'print "Strict mode test\n"'

通常情况下,你会将 Perl 程序写在文件中。创建一个名为 hello.pl 的文件(例如,使用 nano hello.pl 或 vim hello.pl),内容如下:

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say'; # 启用 'say' 函数,Perl 5.10+ 版本可用
# 这个脚本打印一条问候语。
say "Hello, Modern Perl World!";

#!/usr/bin/env perl 这一行被称为 ‘shebang’。它告诉操作系统使用在用户环境路径中找到的 perl 解释器,这比硬编码 /usr/bin/perl 更具可移植性。使脚本可执行并运行它:

$ chmod +x hello.pl
$ ./hello.pl

这将产生输出:

Hello, Modern Perl World!

对于 print 或 say 等内建函数,如果含义清晰,函数参数的括号通常是可选的。然而,对于用户定义的子程序 (subroutines) 以及为了代码清晰起见,通常建议使用括号。

say "Hello without parentheses"; # 对于 say/print 常见
say("Hello with parentheses"); # 也可以,有时更清晰
my_custom_function("argument1", "argument2"); # 建议用于用户定义的函数

上面的两个 say 示例产生相同的输出(每个输出占一行)。

Perl 脚本约定俗成地使用 .pl 扩展名。Perl 模块 (modules)(可重用代码库)使用 .pm 扩展名。虽然其他扩展名也可能有效,但遵守这些约定是标准做法。

文件名可以包含字母、数字和下划线。避免使用空格;改用下划线(例如,my_script.pl)。

注释会被 Perl 解释器忽略,用于解释代码。单行注释以井号 (#) 开头,并延伸到行尾:

# 这是一个单行注释。

Perl 也支持 Plain Old Documentation (POD),用于多行注释或嵌入式文档。POD 块以 =begin identifier(或像 =pod 这样的常用快捷方式)开头,以 =cut 结尾。

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
# 这是一个普通注释。
say "Executable code here.";
=begin comment
这是一个使用 POD 的块注释。
它可以跨越多行。
这些行会被解释器忽略。
=cut
say "More executable code.";

这个程序将输出:

Executable code here.
More executable code.

在引用字符串之外,Perl 对空白字符 (whitespace) 很灵活。以下对于解释器来说是等价的:

say "Hello";
say "Hello" ;
say
"Hello"
;

然而,一致的缩进和间距对于可读性至关重要。在引用字符串内部,空白字符是字面量:

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
say "Hello world"; # 空格被保留
say "Hello\nworld"; # 换行符被解释

这将输出:

Hello world
Hello
world

只包含空白字符的行(可能带有注释)是空白行,会被 Perl 忽略。

引号:单引号、双引号和类引号运算符

Section titled “引号:单引号、双引号和类引号运算符”

Perl 提供了几种引用字符串的方法。最常见的是单引号 (’) 和双引号 (”)。

双引号 (""): 进行变量插值 (interpolate variables)(将变量名替换为其值)和转义序列 (escape sequences) 处理(如 \n 表示换行,\t 表示制表符)。

单引号 (”): 几乎按字面处理内容。不进行变量插值(除了 ’ 和 \),只进行极少的转义序列处理。

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my $name = "Alice";
say "Hello, $name!\nWelcome."; # 双引号: $name 被替换, \n 是换行
say 'Hello, $name!\nWelcome.'; # 单引号: $name 和 \n 是字面量

这将产生:

Hello, Alice!
Welcome.
Hello, $name!\nWelcome.

Perl 还提供了类引号运算符 (quote-like operators):q{}(单引号效果)、qq{}(双引号效果)、qw{}(quote words - 按空白字符分割成列表)。这些运算符允许你选择分隔符 (delimiters),这在字符串本身包含引号时很有用。

my $path = q{/usr/local/bin}; # 类似单引号
my $message = qq{She said, "Hi!"}; # 类似双引号
my @words = qw{apple banana cherry}; # 创建 ('apple', 'banana', 'cherry')

Here 文档是创建多行字符串的便捷方法。语法是 <<DELIMITER;,后跟多行文本,并以单独一行上的 DELIMITER 终止。

如果分隔符未加引号或使用双引号(例如 <<EOF 或 <<“EOF”),变量插值和转义序列处理会生效。如果使用单引号(例如 <<‘EOF’),它的行为类似于单引号字符串。

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my $user = "Bob";
my $interpolated_doc = <<"END_MESSAGE";
Dear $user,
This is a message for you.
Thanks!
END_MESSAGE
my $literal_doc = <<'END_LITERAL';
Dear $user,
This will not interpolate $user.
END_LITERAL
say $interpolated_doc;
say "---";
say $literal_doc;

输出:

Dear Bob,
This is a message for you.
Thanks!
---
Dear $user,
This will not interpolate $user.

注意:终止分隔符必须单独占一行,前后不能有空白字符,除非使用 <<~DELIMITER 语法(Perl 5.26+ 版本可用),该语法允许 heredoc 及其终止符带有缩进。

反斜杠 (</code>) 是 Perl 的转义字符 (escape character)。它会赋予后面的字符特殊含义(例如,\n 表示换行),或者移除字符的特殊含义(例如,$ 用于打印字面量美元符号)。

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my $price = 100;
say "The price is \$$price."; # 转义 $ 以便按字面打印
say "This is a path: C:\\Tools"; # 转义 \ 以便按字面打印

输出:

The price is $100.
This is a path: C:\Tools

标识符 (identifier) 是变量、函数等的名称。Perl 变量名以指示其类型的符号 (sigil)($、@、%)开头,后跟一个字母或下划线,然后是字母、数字或下划线的任意组合。

Perl 区分大小写 (case-sensitive)。$myVar 和 $myvar 是不同的变量。标点符号字符(开头的符号 (sigil) 和下划线除外)通常不允许出现在标识符中。