Perl 5.10 入门教程
首先,一点推销
编辑注:本系列基于Doug Sheppard的Perl 入门教程。使用Perl 5.10的文件和字符串入门教程解释了如何使用文件和字符串,而使用Perl 5.10的正规表达式入门教程探讨了正规表达式、匹配和替换。入门教程Perl网络编程展示了如何编写网络程序。
欢迎来到Perl的世界。
Perl是编程语言的瑞士军刀:强大且灵活。它最初由Larry Wall开发,他在20世纪80年代末作为NASA的系统管理员工作,是一名语言学家,目的是使报告处理变得更简单。从那时起,它已经进入到了几个其他领域:自动化系统管理、作为不同计算机系统之间的粘合剂、网络编程、生物信息学、数据处理,甚至应用开发。
为什么Perl在互联网出现时变得如此流行?有两个原因:首先,互联网上所做的大部分事情都是与文本相关的,并且最好用一种专为文本处理设计的语言来完成。更重要的是,Perl在人们需要使用某种东西的时候,比当时可用的替代品要好得多。C语言复杂,可能会产生安全问题(特别是与不受信任的数据一起使用时),Tcl可能有些笨拙,而Python当时并没有立足之地。
Perl也是一个友好的语言。它与你的个人编程风格配合得很好。Perl的口号是“条条大路通罗马”,这对大小问题都适用。更重要的是,Perl非常便携和普及——几乎到处都可以预装——当然,从CPAN有数千个可以自由分发库可用。
在本系列的第一个部分,你将了解一些关于Perl的基本知识,并看到一个小样程序。
关于操作系统的说明
本系列假设您正在使用Unix或类Unix操作系统(Mac OS X和Cygwin符合条件),并且您在/usr/bin/perl处有可用的perl
二进制文件。如果您通过ActivePerl或Strawberry Perl在Windows上运行,那也行;大多数Perl代码都是平台无关的。
您的第一个Perl程序
将此程序保存为名为first.pl的文件
use feature ':5.10';
say "Hi there!";
(传统的第一个程序是说Hello world!
,但我不是传统主义者)。
运行程序。从命令行进入包含此文件的目录,并输入perl first.pl
。你应该看到
Hi there!
友好,不是吗?
我敢肯定你能猜到say
的作用。关于use feature ':5.10';
这一行呢?现在你只需要知道,它允许你使用Perl 5.10中发现的不错的新特性。这是一件非常好的事情。
函数和语句
Perl有一个丰富的内置函数库。它们是Perl的动词,是解释器执行的命令。您可以在perlfunc手册页(从命令行使用perldoc perlfunc
)中看到所有内置函数的列表。几乎所有函数都可以接受一个由逗号分隔的参数列表。
print
函数是Perl中最常用的部分之一。您使用它来显示屏幕上的内容或将信息发送到文件。它将输出作为其参数的列表。
print "This is a single statement.";
print "Look, ", "a ", "list!";
Perl程序由语句组成,每个语句都以分号结束。语句不必单独一行;一行上可以有多个语句。您也可以将单个语句拆分为多行。
print "This is "; print "two statements.\n";
print "But this ", "is only one statement.\n";
等等。那么say
和print
有什么区别?print
语句中的\n
是什么意思?
say
函数的行为与print
函数类似,但它会在其参数的末尾追加一个换行符。它打印所有的参数,然后是一个换行符。总是这样。没有例外。print
,另一方面,只打印您在这些例子中明确看到的内容。如果您想要换行,您必须使用特殊的转义序列\n
自己添加。
use feature ':5.10';
say "This is a single statement.";
say "Look, ", "a ", "list!";
为什么两者都存在?为什么您会选择一个而不是另一个?通常,大多数“显示某些内容”的语句都需要换行。这很常见,所以say
是一个好的默认选择。偶尔您需要更多一点的控制权,所以print
是选项。
请注意,say
比print
短两个字符。这是Perl的一个重要设计原则——常见的事情应该简单。
数字、字符串和引号
Perl中有两种基本数据类型:数字和字符串。
数字很简单;我们所有人都处理过它们。您需要知道的是,您永远不要在Perl中的数字中插入逗号或空格。始终写作10000,而不是10,000或10 000。
字符串稍微复杂一些。字符串是单引号或双引号中的字符集合
'This is a test.'
"Hi there!\n"
单引号和双引号之间的区别在于,单引号意味着其内容应该是字面的,而双引号意味着其内容应该被解释。记得那个字符序列\n
吗?它代表换行符,当它在双引号字符串中出现时,但在单引号中它就是两个字符反斜杠和n
。
use feature ':5.10';
say "This string\nshows up on two lines.";
say 'This string \n shows up on only one.';
(其他两个有用的反斜杠序列是\t
用于插入制表符,以及\\
用于在双引号字符串中插入反斜杠。)
变量
如果函数是Perl的动词,那么变量就是其名词。Perl有三种类型的变量:标量、数组和哈希。分别考虑它们为事物、列表和字典。在Perl中,所有变量名都由一个标点符号、一个字母或下划线,以及一个或多个字母数字字符或下划线组成。
标量是单个事物。这可能是一个数字或一个字符串。标量的名称以美元符号开始,例如$i
或$abacus
。通过告诉Perl它等于什么来给标量赋值
my $i = 5;
my $pie_flavor = 'apple';
my $constitution1789 = "We the People, etc.";
您不需要指定标量是数字还是字符串。这无关紧要,因为当Perl需要将标量作为字符串处理时,它会这样做;当它需要将标量作为数字处理时,它也会这样做。转换是自动发生的。(这与其他许多语言不同,在那些语言中,字符串和数字是两种不同的数据类型。)
如果您使用双引号字符串,Perl将插入您在字符串中命名的任何标量变量的值。这通常非常有用于动态填充字符串
use feature ':5.10';
my $apple_count = 5;
my $count_report = "There are $apple_count apples.";
say "The report is: $count_report";
此代码的最终输出是报告如下:有5个苹果。
。
您可以使用通常的数学运算在Perl中操作数字:加法、乘法、除法和减法。(顺便说一下,Perl中的乘法和除法运算符分别使用*
和/
符号。)
my $a = 5;
my $b = $a + 10; # $b is now equal to 15.
my $c = $b * 10; # $c is now equal to 150.
$a = $a - 1; # $a is now 4, and algebra teachers are cringing.
这很好,但是这个奇怪的my
是什么,为什么它只出现在某些赋值中而不是其他地方?my
运算符告诉Perl你正在声明一个新的变量。也就是说,你向Perl承诺你故意想要在你的程序中使用具有特定名称的标量、数组或哈希。这有两个原因。首先,它帮助Perl帮助你防止打字错误;发现你不小心打错了变量名,花了几个小时找bug是很尴尬的。其次,它帮助你编写更大的程序,其中一个部分使用的变量不会意外地影响其他地方使用的变量。
你还可以使用特殊的运算符,如++
、--
、+=
、-=
、/=
和*=
。这些运算符可以在不需要方程中的两个元素的情况下操作标量的值。有些人喜欢它们,有些人不喜欢。我喜欢它们可以使代码更清晰。
my $a = 5;
$a++; # $a is now 6; we added 1 to it.
$a += 10; # Now it's 16; we added 10.
$a /= 2; # And divided it by 2, so it's 8.
Perl中的字符串没有那么多灵活性。你可以在字符串上使用的唯一基本运算符是连接,这可以说是“组合在一起”的十美元说法。连接运算符是句号。连接和加法是两件事。
my $a = "8"; # Note the quotes. $a is a string.
my $b = $a + "1"; # "1" is a string too.
my $c = $a . "1"; # But $b and $c have different values!
记住,Perl在必要时会透明地将字符串转换为数字,所以要获取$b
的值,Perl解释器将两个字符串"8"
和"1"
转换为数字,然后相加。$b
的值是数字9。然而,$c
使用了连接,所以它的值是字符串"81"
。
记住,加号加数字,句号连接字符串。如果你添加的不是数字,Perl会尽力做你告诉它做的事,并尽可能地将其非数字转换为数字。
数组是标量的列表。数组名以@
开头。你通过在括号中列出其内容并用逗号分隔来定义数组
my @lotto_numbers = (1, 2, 3, 4, 5, 6); # Hey, it could happen.
my @months = ("July", "August", "September");
你可以通过一个索引来检索数组的内容,有点像“嘿,给我一年的第一个月”。Perl中的索引从零开始。(为什么不是1?因为。这是一个计算机的事情。)要检索数组的元素,你用$
替换@
,然后跟着你想要元素的索引位置。(它以美元符号开头,因为你正在获取一个标量值。)你也可以像任何其他标量一样就地修改它。
use feature ':5.10';
my @months = ("July", "August", "September");
say $months[0]; # This prints "July".
$months[2] = "Smarch"; # We just renamed September!
如果数组中的值不存在,当你对它赋值时,Perl会为你创建它。
my @winter_months = ("December", "January");
$winter_months[2] = "February";
数组总是以相同的顺序返回它们的元素;无论你多少次从开始到结束遍历@months
,你都会以同样的顺序得到七月
、八月
和九月
。如果你想找到数组的元素数量,将数组赋给一个标量。
use feature ':5.10';
my @months = ("July", "August", "September");
my $month_count = @months;
say $month_count; # This prints 3.
my @autumn_months; # no elements
my $autumn_count = @autumn_months;
say $autumn_count; # this prints 0
一些编程语言将哈希称为“字典”。这就是它们的含义:一个术语和一个定义。更确切地说,它们包含键和值。哈希中的每个键都只有一个对应的值。哈希的名称以百分号开头,例如%parents
。你通过逗号分隔键和值的对来定义哈希
my %days_in_month = ( "July" => 31, "August" => 31, "September" => 30 );
你可以通过引用$hashname{key}
从哈希中获取任何值,或者像任何其他标量一样就地修改它。
say $days_in_month{September}; # 30, of course.
$days_in_month{February} = 29; # It's a leap year.
要查看哈希中的键,使用具有哈希名称的keys
函数。这返回一个包含哈希中所有键的列表。列表不一定按顺序排列;虽然你可以确信@months
总是以七月
、八月
、九月
的顺序返回,但keys %days_in_month
可能以任何顺序返回。
my @month_list = keys %days_in_month;
# @month_list is now ('July', 'September', 'August', 'February')!
这三种类型的变量有三个不同的命名空间。这意味着$abacus
和@abacus
是两个不同的变量,而且$abacus[0]
(@abacus
的第一个元素)不等于$abacus{0}
(在%abacus
中具有键0
的值)。
注释
上一节的一些代码示例包含了代码注释。这些注释对于解释特定代码片段的功能非常有用,对于任何计划修改、增强、修复或再次查看的代码来说都是至关重要的。(也就是说,注释很重要。)
Perl代码行中跟随#
符号的任何内容都是注释,除非该#
符号出现在字符串中。
use feature ':5.10';
say "Hello world!"; # That's more like it.
# This entire line is a comment.
循环
几乎每个编写过的程序都使用某种类型的循环。循环允许你反复运行特定的代码片段。这是编程中称为流程控制的一般概念的一部分。
Perl有几种不同的用于流程控制的函数,其中最基本的是for
。当你使用for
函数时,你指定一个用作循环索引的变量,以及一个要循环遍历的值列表。在一对大括号内,你可以放入你想要在循环中运行的任何代码。
use feature ':5.10';
for my $i (1, 2, 3, 4, 5) {
say $i;
}
这个循环打印出1到5的数字,每个数字占一行。(它不是很实用;你可能想“为什么不直接写say 1, 2, 3, 4, 5;
呢”?这是因为say
只在它的参数列表的末尾添加一个换行符。)
定义循环值的一个便捷快捷方式是使用范围运算符..
,它可以指定一个数字范围。你可以将(1, 2, 3, 4, 5)
写成(1 .. 5)
。你还可以在循环列表中使用数组和标量。尝试运行这段代码看看会发生什么。
use feature ':5.10';
my @one_to_ten = (1 .. 10);
my $top_limit = 25;
for my $i (@one_to_ten, 15, 20 .. $top_limit) {
say $i;
}
当然,你也可以写say @one_to_ten, 15, 20 .. $top_limit;
你的循环列表中的项目不一定是数字;你也可以轻松地使用字符串。如果哈希%month_has
包含月份的名称和每个月的天数,你可以使用keys
函数来遍历它们。
use feature ':5.10';
for my $i (keys %month_has) {
say "$i has $month_has{$i} days.";
}
for my $marx ('Groucho', 'Harpo', 'Zeppo', 'Karl') {
say "$marx is my favorite Marx brother.";
}
复利奇迹
你现在对Perl已经足够了解——变量、print
/say
和for()
——可以编写一个小的、有用的程序。每个人都喜欢钱,所以第一个示例程序是一个复利计算器。它将打印出一个格式较好的表格,显示投资在多年后的价值。(你可以在compound_interest.pl
中看到程序。)
程序中最复杂的一行是
my $interest = int( ( $apr / 100 ) * $nest_egg * 100 ) / 100;
$apr / 100
是利率,($apr / 100) * $nest_egg
是一年内获得的利息金额。这一行使用了int()
函数,它返回标量的整数值(其值在去除任何小数部分后)。我们在这里使用int()
,因为当你将10925乘以9.25%时,结果是1010.5625,我们必须将其四舍五入到1010.56。为此,我们将其乘以100,得到101056.25,然后使用int()
去掉剩余的小数部分,得到101056,然后再除以100,这样最终的结果就是1010.56。试着自己执行这个语句,看看我们是如何得到正确结果的,四舍五入到分。
玩玩吧!
到现在为止,你已经对Perl语法有一些基本的了解,还有一些简单的玩具可以玩。试着用它们编写一些简单的程序。这里有两个建议,一个简单,另一个稍微复杂一些。
- 一个单词频率计数器。每个单词在单词数组中出现了多少次?打印出一份报告。(提示:使用哈希来计算每个单词的出现次数。)
- 给定一个月份和该月第一天的星期,打印出该月的日历。
标签
反馈
这篇文章有什么问题吗?请帮助我们通过在GitHub上打开一个issue或pull request来解决问题。