PERL编程24学时教程——09 其他函数和运算符.pdf
-
资源ID:70332702
资源大小:475.93KB
全文页数:11页
- 资源格式: PDF
下载积分:15金币
快捷下载
会员登录下载
微信登录下载
三方登录下载:
微信扫一扫登录
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
|
PERL编程24学时教程——09 其他函数和运算符.pdf
下载第二部分高级特性第9学时其他函数和运算符第1 0学时文件与目录第11学时系统之间的互操作性第1 2学时使用P e r l的命令行工具第1 3学时引用与结构第1 4学时使用模块第1 5学时了解程序的运行性能第1 6学时Perl 语言开发界下载第9学时其他函数和运算符P e r l遵循的传统原则是“一件事情可以使用许多方法来完成”。在本学时中,我们将要更加深入地掌握这个原则。我们将要学习丰富多彩的新函数和运算符。为了进行标量搜索和操作,到现在为止我们一直使用正则表达式。不过我们可以使用多种方法来完成这项任务,P e r l提供了各种各样的函数,以便对标量进行搜索和编辑。在本学时中,我们将要介绍其他的几种方法。另外,我们介绍了作为项目的线性列表的数组,你可以使用 f o r e a c h迭代通过这些列表,或者使用j o i n将它们组合起来,构成标量。在本学时中,我们将要介绍一种观察数组的全新方法。最后,我们要重新介绍一下常用的 p r i n t函数,并且给它增加一点特性。使用新的改进后的p r i n t函数,你就能够编写格式优美、适合向他人展示的报表。在本学时中,你将要学习:如何对标量进行简单的字符串搜索。如何进行字符替换。如何使用p r i n t函数。如何将数组用作堆栈和队列。9.1 搜索标量正则表达式非常适合对标量进行搜索,以便找出你要的模式,但是有时使用正则表达式来搜索标量有点像杀鸡用牛刀的味道。在p e r l中,对模式进行组装,然后在标量中搜索该模式,需要花费一定的开销,不过这个开销并不大。另外,当你编写正则表达式时,很容易出错。为此,p e r l提供了若干个函数,用于对标量进行搜索,或者从标量中取出简单的信息。9.1.1 用index进行搜索如果你只想在另一个标量中搜索单个字符串,Pert提供了index函数。index函数的句法如下:i n d e x函数从s t r i n g的左边开始运行,并搜索 s u b s t r i n g。i n d e x返回找到s u b s t r i n g时所在的位置,o是指最左边的字符。如果没有找到 s u b s t r i n g,i n d e x便返回-1。被搜索的字符串可以是字符串直接量,可以是标量,也可以是能够返回字符串值的任何表达式。s u b s t r i n g不是一个正则表达式,它只是另一个标量。请记住,你编写的P e r t函数和运算符可以带有包含参数的括号,也可以不带。下面是一些例子:根据情况,可以给i n d e x函数规定一个字符串中开始进行搜索的起始位置,如下面的例子显示的那样。若要从左边开始搜索,使用的起始位置是 0:也可以使用带有起始位置的 i n d e x函数,以便“遍历”一个字符串,找到出现一个较短字符串的所有位置,如下所示:上面这个代码滑动通过s o u r c e,如下所示:9.1.2 用rindex向后搜索函数r i n d e x的作用与i n d e x基本相同,不过它是从右向左进行搜索。它的句法如下所示:当搜索到结尾时,r i n d e x返回-1。下面是一些例子:用于i n d e x的遍历循环与使用r i n d e x进行向后搜索的循环略有不同。r i n d e x的起点必须从字符的结尾开始,或者从结尾的后面开始,(在下例中,从l e n g t h($s o u r c e)开始),但是,当返回-1时,它仍然应该结束运行。当找到每个字符串后,s t a r t必须递减1,而不是像i n d e x那样递增1。9.1.3 用substr分割标量s u b s t r是个常常被忽略和很容易被遗忘的函数,不过它提供了一种从标量中取出信息并对标量进行编辑的通用方法。s u b s t r的句法如下:104使用第二部分高 级 特 性下载s u b s t r函数取出s t r i n g,从位置o ff s e t开始运行,并返回从o ff s e t到结尾的字符串的剩余部分。如果设定了l e n g t h,那么取出l e n g t h指明的字符,或者直到找出字符串的结尾,以先到者为准,如下例所示:如果o ff s e t设定为负值,s u b s t r函数将从右边开始计数。例如,s u b s t r($a,-5)返回$a的最后5个字符。如果l e n g t h设定为负值,则s u b s t r返回从它的起点到字符串结尾的值,少于 l e n g t h指明的字符,如下例所示:在上面这个代码段中,s u b s t r从位置5开始运行,返回字符串的剩余部分,但不包含最后1 0个字符。你也可以使用赋值表达式左边的 s u b s t r函数。当用在左边时,s u b s t r用于指明标量中的什么字符将被替换。当用在赋值表达式的左边时,s u b s t r的第一个参数必须是个可以赋值的值,比如标量变量,而不应该是个字符串直接量。下面是使用 s u b s t r对字符串进行编辑的一个例子:9.2 转换而不是替换下一个运算符是转换运算符(有时称为翻译运算符),它使我们想起正则表达式中的替换的操作方式。替换操作符的形式是 s/p a t t e r n/r e p t a c e m e n t/,在第6学时中我们已经作了介绍。除非你用连接运算符设定了另一个标量,否则该操作符将对 _变量进行操作。转换操作符的作用与它有些类似,不过它并不使用正则表达式,而且它的运行方式完全不同。转换操作符的句法如下所示:转换操作符t r/用于搜索一个字符串,找出s e a r c h l i s t中的各个元素,并用r e p l a c e m e n t l i s t中的对应元素对它们进行替换。按照默认设置,转换操作符用于对变量 _进行搜索和修改。若要搜索和修改其他变量,你可以像使用正则表达式进行匹配操作那样,使用连接运算符,如下所示:字符的逻辑分组之间可以使用连字符。例如 AZ代表大写字母A到Z,这样你就不必将它们全部写出来,请看下例:如果r e p l a c e m e n t l i s t是空的,或者与s e a r c h l i s t相同,那么t r/将计算并返回匹配的字符。目第9学时 其他函数和运算符使用105下载标字符串并不被修改,如下例所示:最后要说明的是,由于历史的原因,t r/也可以写成y/,其结果相同,因为 y与t r同义。t r/运算符(和y/)也允许你为s e a r c h l i s t和r e p l a c e m e n t l i s t设定另一组界限符。这些界限符可以是任何一组自然配对的字符,如括号或任何其他字符,请看下面的例子:t r/运算符实际上还具备另外一些功能,不过用得不多。若要了解 t r/能够执行的所有其他任务,请查看p e r l o p节中的在线文档。9.3 功能更强的print函数p r i n t函数是个非常简单的输出函数,它几乎不具备任何格式化功能。为了更具体地控制输出操作,如左对齐和右对齐,十进制精度,以及固定宽度的输出,你可以使用 P e r l的p r i n t f函数。p r i n t f函数是从C编程语言那里借用的(几乎是原原本本的借用),不过其他编程语言也配有类似的函数,如B A S I C的print using函数。p r i n t f函数的句法如下:f o r m a t s t r i n g是一个描述输出格式的字符串,下面我们很快就要对它进行介绍。l i s t是一个你想让p r i n t f显示的值的列表,它类似 p r i n t语句中的l i s t。通常而言,p r i n t f将它的输出显示给S T D O U T文件句柄,但与p r i n t一样,如果你设定了一个文件句柄,那么 p r i n t f就使用该文件句柄。请注意,f i l e h a n d l e名与f o r m a t s t r i n g之间不使用逗号。通常情况下f o r m a t s t r i n g是个字符串直接量,它也可以是一个用来描述输出格式的标量,f o r m a t s t r i n g中的每个字符均按其原义输出,但是以开头的字符则属例外。表示这是一个域说明符的开始。域说明符的格式是-w.d x,其中w是域需要的总宽度,d是小数点左边的位数(对于数字来说)和字符串域允许的总宽度,x表示输出的是数据类型。x说明符前面的连字符表示该域在 w字符中左对齐,否则它进行右对齐。只有和x是不可少的。表9-1列出了一些不同类型的域说明符。106使用第二部分高 级 特 性减号(可有可无)域限定符标记域的总宽度(必须有)小数点后边的位数(可有可无)小数点(可有可无)域类型(必须有)表9-1 Printf函数的部分域说明符列表域类型含义c字符s字符串d十进制整数;截尾的小数f浮点数下载完整的域说明符列表请参见在线手册。你可以在命令提示符后面键入 perldoc-f printf,以查看该列表。下面是使用p r i n t f的一些例子:每个格式说明符均使用列表中的一个项目,如上所示。对于每个项目来说,都应该有一个格式说明符;对于每个格式说明符来说,都有一个列表元素:若要输出数字中的前导0,只需要在格式说明符中的宽度的前面设置 1个0,如下所示:s p r i n t f函数与p r i n t f几乎相同,不过它不是输出值,而是输出 s p r i n t f返回的格式化输出,你可以将它赋予一个标量,或者用于另一个表达式,如下所示:请记住,带有f格式说明符的p r i n t f和s p r i n t f函数能够将计算结果圆整为你指定的小数点位数。9.4 练习:格式化报表当你使用计算机时,必然要处理的一项任务是将原始数据格式化为一个报表。计算机程序能够按照不同于人类阅读的格式对数据进行交换,常见的任务是使用该数据,并将它格式化为人能够阅读的报表。为了进行这个练习,我们为你提供了一组员工记录,它包含关于某些虚构员工的信息,包括每小时的工资、工作的小时数、名字和员工号码。这个练习使用这些数据将它们重新格式化为一个很好的报表。你可以很容易地修改这种类型的程序,以便输出其他类的报表。这个练习的数据包含在一个在程序开始初始化的数组中。在真实的报表中,数据可能来自磁盘上的一个文件。后面我们还要修改这个练习,以便使用外部的文件。使用文本编辑器,键入程序清单 9-2中的程序,并将它保存为 E m p l o y e e,不要键入行号。按照第1学时中的说明,使该程序成为可执行程序。当完成上述操作后,在命令行提示符后面键入下面的命令,设法运行该程序。Perl Employee程序清单9-1显示了E m p l o y e e程序的输出举例。程序清单9-1 Employee程序的输出第9学时 其他函数和运算符使用107下载程序清单9-2 Employee程序的完整清单第1行:这一行包含到达解释程序的路径(可以更改这个路径,使之适合系统的需要)和开关-w。请始终使警告特性处于激活状态。第3行:use strict命令意味着所有变量都必须用m y进行声明,裸单词必须用引号括起来。第5 11行:员工列表被赋予 e m p l o y e e s。数组中的每个元素均包含名字、姓、员工号、计时工资和工作的小时数。第2 3 3 0行:e m p l o y e e s数组按姓和名字排序。第2 4行:被排序的第 1个元素(a)分割为各个域。姓被赋予 L 1,名字被赋于 F 1。两者都用m y声明为排序块的专用变量。第2 5行:对另一个元素b进行与上面相同的操作。姓名被赋于 L 2和L 1。第2 6 2 9行:使用类似第 4学时中的程序清单 4-1介绍的顺序,按字母对各个名字进行比较。第3 2 3 4行:e m p l o y e e s中的已排序列表被传递给p r i n t-e m p(),每次传递一个元素。108使用第二部分高 级 特 性下载第1 3 2 1行:p r i n t-e m p()函数输出格式化很好的员工记录。第1 4 1 5行:传递来的记录$_ 0 被分割成各个域,并被赋于变量 l a s t,f i r s t等,它们都是该子例程的专用变量。第1 7行:名字和姓被合并为单个域,这样,两个域就可以放入某个宽度,并一道对齐。第1 8 2 0行:记录被输出。h o u r s与t i m e相乘,得出合计金额。金额.0 0 5与合计相加,这样,当乘积被截尾而成为两位数时,它能正确地圆整。9.5 堆栈形式的列表到现在为止,列表(和数组)一直是作为线性数据数组来展示的,其索引用于指明每个元素。请使用你的想象力,将各个组数元素设想为一个纵向堆栈。在计算机术语中,这种列表称为堆栈。堆栈可用于按顺序来处理的累计操作。Klondike Solitaire游戏就是一个很好的例子。7堆牌中的每一堆牌分别代表一个堆栈;开始时,这些牌面向下放入堆栈。当需要这些牌时,它们被翻过来,并从堆栈中取走,再将其他牌放在新翻过来的牌的上面。P e r l中的堆栈通常用数组来实现。若要将各个项目放在堆栈的顶部,可以使用p u s h函将项目压入堆栈;若要将项目从堆栈的顶部取出,可以使用 p o p函数。另外,堆栈可以从底部进行修改,可以将它视为从一叠纸牌的底部对它进行处理一样。S h i f t函数用于将元素添加到堆栈的底部,u n s h i f t用于从底部取出元素。每个函数的句法如下:p o p与s h i f t函数分别从t a rg e t _ a r r a y中删除一个元素。如果t a rg e t _ a r r a y没有设定,那么元素可以从 _中删除,也可以从 A R G V中删除。p o p和s h i f t函数返回被删除的元素,如果数组是第9学时 其他函数和运算符使用109下载0苹果桃梨李子芒果石榴石榴芒果李子梨桃苹果12345推送菠萝石榴弹出芒果李子梨桃转移转移葡萄苹果空的,则返回u n d e f。数组的大小将相应地缩小。在子例程中,如果没有设定其他数组,那么 p o p、s h i f t、u n s h i f t和p u s h函数将修改 _。在子例程外面,你的程序主体中,如果没有设定其他数组,那么这些函数将修改数组 A R G V。p u s h和u n s h i f t函数将n e w _ l i s t的元素添加给t a rg e t _ a r r a y,数组的大小将增大,以适应放置新元素的需要。被放入t a rg e r _ a r r a y的项目,或者从t a rg e t _ a r r a y取出的项目既可以是一个列表,也可以是一个数组,如下例所示:当你将元素添加给数组时,将元素推送(或移动)到数组中要比用手工将元素添加到数组的结尾处更加有效。比如,p u s h(l i s t,n e w i t e m s)比 l i s t=(l i s t,n e w i t e m s)更加有效。P e r l的p u s h、s h i f t、u n s h i f t和p u p函数都进行了优化,以适应这些操作的需要。“堆栈”中的数组元素仍然属于标准的数组元素,可以用索引进行编址。堆栈的“底部”是元素0,堆栈的“顶部”是数组中的最后一个元素。拼接数组迄今为止,我们介绍了数组可以按元素进行寻址、分行、移动、弹出、取消移动和推送。数组操作的最后一个工具是s p l i c e。s p l i c e函数的句法如下:s p l i c e函数用于删除数组中从 o ff s e t位置开始的元素,同时返回被删除的数组元素。如果o ff s e t的值是负值,则从数组的结尾处开始计数。如果设定了 l e n g t h,那么只删除l e n g t h指定的元素。如果设定了l i s t,则删除l e n g t h指定的元素,并用l i s t的元素取代之。通过这个处理过程,数组就会根据需要扩大或缩小,如下面所示的那样:9.6 课时小结在本学时中,我们介绍了搜索其他字符串中的字符串时不需要使用正则表达式,你可以110使用第二部分高 级 特 性下载使用i n d e x和r i n d e x进行简单的搜索,也可以使用 t r/运算符进行简单的替换。s u b s t r函数既可以用来从字符串中检索数据,也可以对它们进行编辑。你可以使用 p r i n t f和s p r i n t f语句,用P e r l创建格式很好的输出。另外,我们介绍了用作项目堆栈而不是平面列表的数组,还学习了如何对这些堆栈进行操作。9.7 课外作业9.7.1 专家答疑问题:s u b s t r、i n d e x和r i n d e x等函数真的有必要使用吗?当正则表达式可以用来执行它们的大多数操作时,为什么还要这几种函数?解答:首先,用于进行简单的字符串搜索的正则表达式的运行速度比i n d e x和r i n d e x慢。第二,为字符位置固定的正则表达式编写替换表达式会产生很大的混乱,而有时 s u b s t r则是比较出色的解决方案。第三,P e r l是一种丰富多彩的语言,你可以使用你喜欢的解决方案,你可以有多种多样的选择。问题:如果我设定的索引位于标量的结尾之外,使用 s u b s t r(或i n d e x或r i n d e x)将会出现什么情况?解答:计算机的好处之一是:它具有很强的一致性,而且它有很强的耐心。对于“如果将会出现什么情况”之类的问题,有时你只要试一试它的最容易实现的方法即可!什么是可能出现的最坏情况呢?在这种情况下,如果你激活了警告特性,那么访问并不存在的标量的某个部分,就会产生一个“use of undefined value”(使用了未定义的值)的错误。例如,如果你使用a=“F o o”;s u b s t r(a,5);那么s u b s t r函数将返回u n d e f。9.7.2 思考题1)假如有下面这个代码,那么在 A中将留下什么?a.oats peas beansb.deans barleyc.peas beans barley2)printf(“%1 8.3 f”,a)这个代码能够进行什么操作?a.它输出一个浮点数,长度为 1 8个字符,小数点左边是 1 5个字符,小数点右边是 3个字符。b.它输出一个浮点数,小数点左边是 1 8个字符,小数点右边是3个字符。c.它输出一个浮点数,长度为1 8个字符,小数点左边是1 4个字符,右边3个字符。3)如果对一个字符串运行t r/a-z/A-Z,t r/A-Z/a-z能否使字符串恢复其原始形式?a.是,当然能够。b.也许做不到。第9学时 其他函数和运算符使用111下载9.7.3 解答1)答案是c。s h i f t删除了c a t s,而p u s h则将b a r l e y添加到结尾处。最后的 p o p是个假像,它并没有设定任何数组,因此它从array _中弹出某些数据,但是它没有给 A带来任何变化。2)答案是c。如果你猜测的答案是 a,那么你没有将小数点计算在内,它在总数(1 81 413)中占有一个位置。3)答案是b。t r/a-z/A-Z/转换的“r o s e b u d”变成了“R O S E B U D”。如果试图用t r/A-Z/a-z/将它变回原样,那么产生的是“r o s e b u d”,而不是原始字符串。9.7.4 实习 使用标量而不是数组,重新编写第 4学时中的H a n g m a n游戏。你可以使用s u b s t r,对标量中的各个字符进行操作。修改程序清单9-2,从文件中读取数据,而不是从数组中获取数据。打开文件,将数据读入一个数组,然后按正常情况继续操作。当然你必须在磁盘上创建该文件。112使用第二部分高 级 特 性下载