两个半小时用阿拉伯数字字体大全怎么表示

哎呀,服务正在维护中……
休息一下,马上回来!您现在的位置: &
两个半小时的Perl飞升之旅(1)
两个半小时的Perl飞升之旅(1)
  Perl语言是一门高级解释型动态语言,它的许多数据类型是运行时才确定的,并且经常和PHP和 Python相提并论。Perl从古老的Shell脚本语言中借鉴了许多语法特性,因为被过度使用的各种奇怪符号而声名狼藉,而且许多代码即使借助 Google的搜索功能都不能完全看明白。许多来自 Shell 的语言特性使之成为一门好用的胶水语言: 将其他语言和脚本连接在一起共同工作。
  语言非常适合处理文本,并生成更多的文本。Perl语言应用广泛,流行,可移植性极佳,而且有良好的社区支持。Perl 语言的设计哲学是:&每个问题都有许多解决方式&(TMTOWTDI)( 与之相反,Python的设计哲学是:每个问题应该只有一种,而且只有一种明确的,最好的解决方式)。
  Perl有令人沮丧的地方,但同时也有许多奇妙的特性。从这一点来看,它同其他任何一种曾经有过的编程语言一样。
  这篇文章只是提供一些知识,并不是什么宣传广告,目标读者只是针对像我这样的人:
  &厌恶 上面学术性的文档,那些东西只会长篇累牍的讲述一些永远用不到的边缘问题。
  &我只想通过一些通用规则和实例快速了解那些从Larry Wall的角度永远都不关心的基础编程问题
  &学些能帮我找到一份工作的基础知识
  这篇文档的目的是用短的不能再短的形式来讲。
  研究初探
  以下声明针对整个文档:&这并不是绝对的,实际情况要复杂的多&。你如果发现一个严重错误,请告诉我。但我保留对孩子们说错话的权利。
  在本文档中,我在实例中打印状态,输出数据,但没有明确的追加换行符。这样做是为了避免我发狂,让我能集中精力在实例中字符串的输出,我相信这是更重要的。在许多例子中,实际的输出可能是 &alotofwordsallsmusheduptogetherononeline&. 请不要在意。
  Hello world
  一个 Perl 脚本就是一个后缀为 .pl 的文本文件。
  这就是 helloworld.pl 的全文:
  use& &  use& &  print&&Hello&world&;&
  Perl 脚本被 Perl 的解释器来解释运行,perl 或者 perl.exe:
  perl&helloworld.pl&[arg0&[arg1&[arg2&...]]]&
  说实话, Perl的语法非常宽容,他可以替你预测一些模糊的不知所云的代码的行为,我实在不想讲这些东西,因为你们应当竭力避免这么做。
  避免这么做的方法就是将 ' use warnings' 放置在每一个脚本或模块的最前面。'use foo' 这样的语句是编译提示,编译提示是给 Perl.exe 的信号,在程序运行前,对解释器初始化语法验证规则施加影响。在代码运行的时候,解释器将忽略这些东西。' #' 符号是一个注释的开始。注释的结束是到行的末尾。Perl 没有针对块的注释语法。
  Perl的变量有三种类型:标量(scalar),数组(array)和哈希(hash)。每种类型有它自己的记号,分别是¥,@和%。变量用my声明,保存到封闭的块(enclosing block)或者文件(file)的结尾。
  标量变量
  &标量变量可以储存:
  &undef(和Nonein Python,nullin PHP一致)
  &一个数字(Perl不区分整数(integer)和浮点(float))
  &字符串
  引用任何其他变量。
  my&$undefundef&=& &  print&$&#&prints&the&empty&string&&&&and&raises&a&warning &  #&implicit&undef: &  my&$undef2; &  print&$undef2;&#&prints&&&&and&raises&exactly&the&same&warning&
  my&$num&=&4040.5; &  print&$&#&&4040.5&&
  my&$string&=&&world&; &  print&$&#&&world&&
  (引用的用法稍后讲述。)
  用.操作符实现字符串的链接(和PHP一样):
  print&&Hello&&.$&#&&Hello&world&&
  布尔值(Booleans)
  Perl 没有布尔数据类型。只有如下几种值才能在 if 判断语句中返回 'false' :
  &undef
  &数字 0
  &字符串 &&
  &字符串 &0&
  Perl 文档中经常提到函数在某些情况下会返回 'true' 或 'false'. 实际上,函数通常用 'return 1' 来返回真,用返回空字符串 '' 来表示返回假。
  弱类型(Weak typing)
  断定一个标量中存储的到底是一个数字或是一个字符串,这是不可能的。更进一步说,根本没必要去确定这个问题。一个标量的行为到底像一个数字或字符串完全取决于它的操作符。当做一个字符串用的时候,标量表现的就是一个字符串,而当做一个数字来用时,它又变成了数字。(如果不可能转换就会有个警告):
  my&$str1&=&&4G&; &  my&$str2&=&&4H&; &  print&$str1&.&&$str2;&#&&4G4H& &  print&$str1&+&&$str2;&#&&8&&with&two&warnings &  print&$str1&eq&$str2;&#&&&&(empty&string,&i.e.&false) &  print&$str1&==&$str2;&#&&1&&with&two&warnings &  #&The&classic&error &  print&&yes&&==&&no&;&#&&1&&with&two&&both&values&evaluate&to&0&when&used&as&numbers&
  座右铭就是一直用相应的情况下使用合适的操作符。在标量比较中,字符串和数字分别有两套不同的操作符:
  #&数字操作符:&&&&&,&&&,&&=,&&=,&==,&!=,&&=&,&+,&* &  #&字符串操作符:&&lt,&gt,&le,&ge,&eq,&ne,&cmp,&.,&x&
  数组型变量(Array variables)
  一个数组型变量是以 0 为索引开始的一组标量列表。在 Python 中被成为 list, 在 PHP 中被称为 array. 一个数组的声明使用一个被括号包围的标量列表:
  my&@array&=&( &  &&&print&, &  &&&these&, &  &&&strings&, &  &&&out&, &  &&&for&, &  &&&me&,&#&后面的逗号是允许的 &  );&
  你不得不使用一个美元符号前缀访问一个数组的元素,因为被取出的元素不再是数组,而是一个标量:
  print&$array[0];&#&&print& &  print&$array[1];&#&&these& &  print&$array[2];&#&&strings& &  print&$array[3];&#&&out& &  print&$array[4];&#&&for& &  print&$array[5];&#&&me& &  print&$array[6];&#&返回&undef,&打印&&&&并提示一个警告&
  你们可以使用负数索引来检索从后往前的元素:
  print&$array[-1];&#&&me& &  print&$array[-2];&#&&for& &  print&$array[-3];&#&&out& &  print&$array[-4];&#&&strings& &  print&$array[-5];&#&&these& &  print&$array[-6];&#&&print& &  print&$array[-7];&#&返回&undef,&p打印&&&&并提示一个警告&
  在一个 $var 和 @var 中包含的 $var[0] 之间并没有什么关系, 但这可能让阅读的人迷糊,因此应当避免这么做。
  获取数组的长度:
  print&&This&array&has&&.(scalar&@array).&elements&;&#&&这个数组有6个元素& &  print&&The&last&populated&index&is&&.$#&&&#&&最后一个索引的号码是&5&&
  Perl 脚本捕获的命令行参数被保存在内置的数组变量 @ARGV 中。
  print&&Hello&$string&;&#&&Hello&world& &  print&&@array&;&&&&&&&&#&&print&these&strings&out&for&me&&
  小心,有天你会把一个电子邮件地址放置到一个字符串中,例如 &&. 这将导致Perl将一个数组型变量 @gmail 内插到字符串中,而且无法找到这个变量,并引起一个运行错误。这个问题可以通过两种方式解决:转义这个变量前置符,或使用单引号而不是双引号来引起字符串。
  print&&Hello&\$string&;&#&&Hello&$string& &  print&'Hello&$string';&&#&&Hello&$string& &  print&&\@array&;&&&&&&&&#&&@array& &  print&'@array';&&&&&&&&&#&&@array&&
  哈希型变量
  哈希型变量是按照字符串来进行索引的列表。在 Python 中称为字典,而在 PHP 中被称为关联数组。
  my&%scientists&=&( &  &Newton&&&&=&&&Isaac&, &  &Einstein&&=&&&Albert&, &  &Darwin&&&&=&&&Charles&, &  ); &
  请注意散列的声明和数组何其相似。实际上,双箭头符号 =& 也叫胖逗号,因为他只是逗号的同义符号。一个散列由偶数个元素列表组成,所有偶数位置的元素都将被保存为字符串。
  再一次,你不得不使用一个美元符号前缀来获取一个散列的值,因为被取出的值不再是一个散列,而是一个标量。
  print&$scientists{&Newton&};&&&#&&Isaac& &  print&$scientists{&Einstein&};&#&&Albert& &  print&$scientists{&Darwin&};&&&#&&Charles& &  print&$scientists{&Dyson&};&&&&#&returns&undef,&prints&&&&and&raises&a&warning &
  请注意这里使用的是大括号。同样,一个标量 $var 和一个 包含 $var{&foo&} 内容的 %var 没有任何冲突。
  你也可以直接将一个偶数个元素的数组转换成散列,这些元素将交错的成为键和值(转换回来也同样容易).
  my&@scientists&=&%&
  然而,不像数组,散列的键没有特定的保存顺序。键值在内部是以一种非常高效的方式保存,因此要注意返回的数组的顺序会被成对的重新排列:
  print&&@scientists&;&#&something&like&&Einstein&Albert&Darwin&Charles&Newton&Isaac &
  回顾一下,你必须使用方括号来从数组中检索一个值, 但必须使用大括号来从散列中检索一个值。方括号实际上是一个数值操作符,而大括号是一个的字符串操作符。事实上,查询索引是一个数字或是字符串都没有关系:
  my&$data&=&&orange&; &  my&@data&=&(&purple&); &  my&%data&=&(&&0&&=&&&blue&); &  print&$&&&&&&#&&orange& &  print&$data[0];&&&#&&purple& &  print&$data[&0&];&#&&purple& &  print&$data{0};&&&#&&blue& &  print&$data{&0&};&#&&blue&&&
  列表(list)
  在 Perl 中,列表 跟数组或哈希表是有区别的。下面是一些列表:
  ( &  &&&&&print&, &  &&&&&these&, &  &&&&&strings&, &  &&&&&out&, &  &&&&&for&, &  &&&&&me&, &  ) &  ( &  &&&&&Newton&&&&=&&&Isaac&, &  &&&&&Einstein&&=&&&Albert&, &  &&&&&Darwin&&&&=&&&Charles&, &  ) &
  列表不是变量。列表是一种可以被分配到数组或哈希表变量中的短小的值。这也是为什么声明数组和哈希表变量的语法相同的原因。虽然有很多时候,&列表&和&数组&可以通用,但也要看到很多时候两者之间的形式有着些许的不同,以及行为的区别。
  好,记住 =& 只是 , 的另一种形式,让我们看看下面的例子:
  (&one&,&1,&&three&,&3,&&five&,&5) &  (&one&&=&&1,&&three&&=&&3,&&five&&=&&5) &
  使用=&的目的是表明下面列表中的一些是数组声明,而另一些是哈希表声明。但他们并没有声明任何东西。他们只是列表。相同的列表。下面也是:
  上面没有表明任何东西。列表可以用来声明一个空的数组或哈希表,显然 Perl 的解释器无法告诉你它究竟是什么。一旦你理解了 Perl 的这种奇怪,你就能够理解列表值不能嵌套是真的了,试试下面的代码:
  my&@array&=&( &  &&&&&apples&, &  &&&&&bananas&, &  &&&&( &  &&&&&&&&&inner&, &  &&&&&&&&&list&, &  &&&&&&&&&several&, &  &&&&&&&&&entries&, &  &&&&), &  &&&&&cherries&, &  ); &
  Perl 永远都无法了解 (&inner&, &list&, &several&, &entries&) 到底是内部数组还是内部哈希表。Perl 会将其展开成为一个长列表,而非上面提到的内部数据。
  print&$array[0];&#&&apples& &  print&$array[1];&#&&bananas& &  print&$array[2];&#&&inner& &  print&$array[3];&#&&list& &  print&$array[4];&#&&several& &  print&$array[5];&#&&entries& &  print&$array[6];&#&&cherries&&
  无论用的是不是逗号,都是这样:
  my&%hash&=&( &  &&&&&beer&&=&&&good&, &  &&&&&bananas&&=&&( &  &&&&&&&&&green&&&=&&&wait&, &  &&&&&&&&&yellow&&=&&&eat&, &  &&&&), &  ); &  #&The&above&raises&a&warning&because&the&hash&was&declared&using&a&7-element&list &  print&$hash{&beer&};&&&&#&&good& &  print&$hash{&bananas&};&#&&green& &  print&$hash{&wait&};&&&&#&&yellow&; &  print&$hash{&eat&};&&&&&#&undef,&so&prints&&&&and&raises&a&warning &
  当然,这使得连接数个数组变得极其容易:
  my&@bones&&&=&(&humerus&,&(&jaw&,&&skull&),&&tibia&); &  my&@fingers&=&(&thumb&,&&index&,&&middle&,&&ring&,&&little&); &  my&@parts&&&=&(@bones,&@fingers,&(&foot&,&&toes&),&&eyeball&,&&knuckle&); &  print&@ &
  更多的内容会在下文提及。
  上下文
  Perl最独特的特点是,代码是上下文敏感的。在Perl中的每一个表达式是通过标量上下文或者列表上下文来计算,这取决于是要生成标量或者是列表。大部分的Perl表达式和内置函数会在不同的上下文中,会表现出很不同的行为。
  标量表达式例如$scalar= 在标量上下文中计算。在本例中,表达式是&Mendeleev&,返回值也是标量&Mendeleev&:
  my&$scalar&=&&Mendeleev&;&
  数组或者哈希值赋值,例如@array = 或者%hash = 则是在列表上下文中演算。在列表上下文中计算的结果会以列表返回,然后赋值给数组或者哈希变量:
  my&@array&=&(&Alpha&,&&Beta&,&&Gamma&,&&Pie&); &  my&%hash&=&(&Alpha&&=&&&Beta&,&&Gamma&&=&&&Pie&);&
  目前位置,没什么特别的。
  标量表达式在上下文中,则以一个元素的列表作为返回值:
  my&@array&=&&Mendeleev&;&#&same&as&'my&@array&=&(&Mendeleev&);'&
  列表表达式在标量上下文中,则以列表的最后一个标量作为返回值:
  my&$scalar&=&(&Alpha&,&&Beta&,&&Gamma&,&&Pie&);&#&Value&of&$scalar&is&now&&Pie&&
  数组表达式(数组和列表是不一样的,还记得吧?)在标量上下文中,返回数组的长度:
  my&@array&=&(&Alpha&,&&Beta&,&&Gamma&,&&Pie&); &  my&$scalar&=&@&#&Value&of&$scalar&is&now&4&
  内置函数 print在列表上下文中计算所有的变量。事实上,print可以对变量中数组的没有限制大小要求,并且逐一打印数组中的元素,这意味着,可以直接打印数组:
  my&@array&=&(&Alpha&,&&Beta&,&&Goo&); &  my&$scalar&=&&-X-&; &  print&@&&&&&&&&&&&&&&#&&AlphaBetaGoo&; &  print&$scalar,&@array,&98;&#&&-X-AlphaBetaGoo98&;&
  你可以强制任何的表达式在标量上下文中计算,只需使用 scalar内置函数。事实上,这就是为什么我们使用scalar去获取数组的长长度。
  perl中没有限制在标量上下文的子过程中一定要返回标量,或者在列表上下文中一定要返回列表。就如上面的例子,Perl可以兼容不同的结果。
  引用和嵌套数据结构
  同列表无法将列表作为自身元素一样,数组和哈希表也无法将另一个数组和哈希表作为自身元素。它们只能包含一个标量,让我们试试看:
  my&@outer&=&(&Sun&,&&Mercury&,&&Venus&,&undef,&&Mars&); &  my&@inner&=&(&Earth&,&&Moon&); &  $outer[3]&=&@ &  print&$outer[3];&#&&2& &
  $outer[3] 是一个标量,因此它需要一个标量值。当你尝试将一个类似 @inner 的数组值分配给它时,@inner 将被计算并存于标量内容分配标量 @inner 时亦是如此,值为数组 @inner 的长度,即为 2。
  不过,一个标量变量可以存放一个对任何变量的引用,包括数组变量或是哈希表变量。使用 Perl 创建复杂的数据结构用的就是这种方式。
  引用使用反斜杠创建。
  my&$colour&&&&=&&Indigo&; &  my&$scalarRef&=&\$ &
  当你使用变量名时,你可以先使用一对大括号,然后将对变量的引用放进大括号内:
  print&$&&&&&&&&&#&&Indigo& &  print&$scalarR&&&&&&#&e.g.&&SCALAR(0x182c180)& &  print&${&$scalarRef&};&#&&Indigo& &
  图省事的话也可以不用大括号:
  print&$$scalarR&#&&Indigo& &
  如果是一个数组或哈希表变量的引用,你可以使用大括号或是比较流行的箭头操作符 -& 获取数据:
  my&@colours&=&(&Red&,&&Orange&,&&Yellow&,&&Green&,&&Blue&); &  my&$arrayRef&=&\@ &  print&$colours[0];&&&&&&&#&direct&array&access &  print&${&$arrayRef&}[0];&#&use&the&reference&to&get&to&the&array &  print&$arrayRef-&[0];&&&&#&exactly&the&same&thing &  my&%atomicWeights&=&(&Hydrogen&&=&&1.008,&&Helium&&=&&4.003,&&Manganese&&=&&54.94); &  my&$hashRef&=&\%atomicW &  print&$atomicWeights{&Helium&};&#&direct&hash&access &  print&${&$hashRef&}{&Helium&};&&#&use&a&reference&to&get&to&the&hash &  print&$hashRef-&{&Helium&};&&&&&#&exactly&the&same&thing&-&this&is&very&common &
  声明数据结构
  下面有4个例子,但通常最后一个更常用。
  my&%owner1&=&( &  &&&&&name&&=&&&Santa&Claus&, &  &&&&&DOB&&&=&&&&, &  ); &  my&$owner1Ref&=&\%owner1; &  my&%owner2&=&( &  &&&&&name&&=&&&Mickey&Mouse&, &  &&&&&DOB&&&=&&&&, &  ); &  my&$owner2Ref&=&\%owner2; &  my&@owners&=&(&$owner1Ref,&$owner2Ref&); &  my&$ownersRef&=&\@ &  my&%account&=&( &  &&&&&number&&=&&&&, &  &&&&&opened&&=&&&&, &  &&&&&owners&&=&&$ownersRef, &  ); &
  显然你不用这么费劲,可以简化为:
  my&%owner1&=&( &  &&&&&name&&=&&&Santa&Claus&, &  &&&&&DOB&&&=&&&&, &  ); &  my&%owner2&=&( &  &&&&&name&&=&&&Mickey&Mouse&, &  &&&&&DOB&&&=&&&&, &  ); &  my&@owners&=&(&\%owner1,&\%owner2&); &  my&%account&=&( &  &&&&&number&&=&&&&, &  &&&&&opened&&=&&&&, &  &&&&&owners&&=&&\@owners, &  ); &
  也可以使用不同的符号声明匿名数组和哈希表。匿名数组使用方括号,匿名哈希表使用大括号。 这样,返回值就是一个对匿名数据结构的引用。细看一下, 返回的 %accountas 与上面相同:
  #&Braces&denote&an&anonymous&hash &  my&$owner1Ref&=&{ &  &&&&&name&&=&&&Santa&Claus&, &  &&&&&DOB&&&=&&&&, &  }; &  my&$owner2Ref&=&{ &  &&&&&name&&=&&&Mickey&Mouse&, &  &&&&&DOB&&&=&&&&, &  }; &  #&Square&brackets&denote&an&anonymous&array &  my&$ownersRef&=&[&$owner1Ref,&$owner2Ref&]; &  my&%account&=&( &  &&&&&number&&=&&&&, &  &&&&&opened&&=&&&&, &  &&&&&owners&&=&&$ownersRef, &  ); &
  或者更短一些(这就是真正用来声明复杂数据结构的形式):
  my&%account&=&( &  &&&&&number&&=&&&&, &  &&&&&opened&&=&&&&, &  &&&&&owners&&=&&[ &  &&&&&&&&{ &  &&&&&&&&&&&&&name&&=&&&Philip&Fry&, &  &&&&&&&&&&&&&DOB&&&=&&&&, &  &&&&&&&&}, &  &&&&&&&&{ &  &&&&&&&&&&&&&name&&=&&&Hubert&Farnsworth&, &  &&&&&&&&&&&&&DOB&&&=&&&&, &  &&&&&&&&}, &  &&&&], &  ); &
  获取信息的数据结构
  现在,让我们假设,(如果有其他任何东西)范围已经下降了你仍然有个%accountkicking,可以打印信息,在每一种情况下扭转了相同的程序。现在这里有四个例子,其中最后一个是最有用的:
  my&$ownersRef&=&$account{&owners&}; &  my&@owners&&&&=&@{&$ownersRef&}; &  my&$owner1Ref&=&$owners[0]; &  my&%owner1&&&&=&%{&$owner1Ref&}; &  my&$owner2Ref&=&$owners[1]; &  my&%owner2&&&&=&%{&$owner2Ref&}; &  print&&Account&#&,&$account{&number&},&&\n&; &  print&&Opened&on&&,&$account{&opened&},&&\n&; &  print&&Joint&owners:\n&; &  print&&\t&,&$owner1{&name&},&&&(born&&,&$owner1{&DOB&},&&)\n&; &  print&&\t&,&$owner2{&name&},&&&(born&&,&$owner2{&DOB&},&&)\n&;&
  或者,简称:
  my&@owners&=&@{&$account{&owners&}&}; &  my&%owner1&=&%{&$owners[0]&}; &  my&%owner2&=&%{&$owners[1]&}; &  print&&Account&#&,&$account{&number&},&&\n&; &  print&&Opened&on&&,&$account{&opened&},&&\n&; &  print&&Joint&owners:\n&; &  print&&\t&,&$owner1{&name&},&&&(born&&,&$owner1{&DOB&},&&)\n&; &  print&&\t&,&$owner2{&name&},&&&(born&&,&$owner2{&DOB&},&&)\n&;&
  或使用引用和&运算符:
  my&$ownersRef&=&$account{&owners&}; &  my&$owner1Ref&=&$ownersRef-&[0]; &  my&$owner2Ref&=&$ownersRef-&[1]; &  print&&Account&#&,&$account{&number&},&&\n&; &  print&&Opened&on&&,&$account{&opened&},&&\n&; &  print&&Joint&owners:\n&; &  print&&\t&,&$owner1Ref-&{&name&},&&&(born&&,&$owner1Ref-&{&DOB&},&&)\n&; &  print&&\t&,&$owner2Ref-&{&name&},&&&(born&&,&$owner2Ref-&{&DOB&},&&)\n&;&
  如果我们完全跳过所有的中间值:
  print&&Account&#&,&$account{&number&},&&\n&; &  print&&Opened&on&&,&$account{&opened&},&&\n&; &  print&&Joint&owners:\n&; &  print&&\t&,&$account{&owners&}-&[0]-&{&name&},&&&(born&&,&$account{&owners&}-&[0]-&{&DOB&},&&)\n&; &  print&&\t&,&$account{&owners&}-&[1]-&{&name&},&&&(born&&,&$account{&owners&}-&[1]-&{&DOB&},&&)\n&;&
  搬起数组引用的石头砸自己的脚
  下面的数组拥有5个元素:
  my&@array1&=&(1,&2,&3,&4,&5); &  print&@array1;&#&&12345& &
  下面的数组拥有一个元素(它刚好是对一个匿名的,拥有5个元素的数组的引用):
  my&@array2&=&[1,&2,&3,&4,&5]; &  print&@array2;&#&e.g.&&ARRAY(0x182c180)& &
  这个标量是对一个匿名的,拥有5个元素的数组的引用:
  my&$array3Ref&=&[1,&2,&3,&4,&5]; &  print&$array3R&&&&&&#&e.g.&&ARRAY(0x22710c0)& &  print&@{&$array3Ref&};&#&&12345& &  print&@$array3R&&&&&#&&12345& &
  条件语句 
  if...elsif...else...
  在这里不要感到惊讶,除了elsif的拼写:
  my&$word&=&&antidisestablishmentarianism&; &  my&$strlen&=&length&$ &  if($strlen&&=&15)&{ &  &&&&print&&'&,&$word,&&'&is&a&very&long&word&; &  }&elsif(10&&=&$strlen&&&&$strlen&&15)&{ &  &&&&print&&'&,&$word,&&'&is&a&medium-length&word&; &  }&else&{ &  &&&&print&&'&,&$word,&&'&is&a&a&short&word&; &  }&
  Perl提供一种更短的& statement &if& condition & 语法,在短语句中这是非常值得推荐的:
  print&&'&,&$word,&&'&is&actually&enormous&&if&$strlen&&=&20;&
  unless...else...
  my&$temperature&=&20; &  unless($temperature&&&30)&{ &  &&&&print&$temperature,&&&degrees&Celsius&is&not&very&hot&; &  }&else&{ &  &&&&print&$temperature,&&&degrees&Celsius&is&actually&pretty&hot&; &  }&
  unless语句块非常混乱,通常最好避免这种犹如瘟疫的东西。一个 &unless [ ... else ] &语言块可以一点点地重构成&if [ ... else] &语句块,可以通过将条件取反 [或保持条件不变,交换语句块的位置]。幸运的是,不存在&elsunless&关键字。
  通过比较,由于易读性这被强烈推荐:
  print&&Oh&no&it's&too&cold&&unless&$temperature&&&15;&
  三元运算符
  三元运算符:?可以将简单的if语句嵌入到一个语句中。它的典型使用是单数/复数形式:
  my&$gain&=&48; &  print&&You&gained&&,&$gain,&&&&,&($gain&==&1&?&&experience&point&&:&&experience&points&),&&!&;&
  旁白:单复数形式最全面阐明了这两种情况。不要自认为聪明做像下面这样的事情,因为任何人搜索的代码库以替换&tooth&或&teeth&,你将永远不会找到这行:
  my&$lost&=&1; &  print&&You&lost&&,&$lost,&&&t&,&($lost&==&1&?&&oo&&:&&ee&),&&th!&;&
  三元运算符可能被嵌套:
  my&$eggs&=&5; &  print&&You&have&&,&$eggs&==&0&?&&no&eggs&&: &  &&&&&&&&&&&&&&&&&&&$eggs&==&1&?&&an&egg&&&: &  &&&&&&&&&&&&&&&&&&&&some&eggs&;&
  if语句在标量的上下文中对它们的条件求值。例如,if(@array)返回真当且仅当@array有一个或多个元素。它并不关心这些元素是什么&&他们可包含undef(未定义)或其它非真值。
  Perl中有多种方法实现循环:
  常规的while循环:
  my&$i&=&0; &  while($i&&scalar&@array)&{ &  &&&&print&$i,&&:&&,&$array[$i]; &  &&&&$i++; &  }&
  Perl同样支持until关键字:
  my&$i&=&0; &  until($i&&=&scalar&@array)&{ &  &&&&print&$i,&&:&&,&$array[$i]; &  &&&&$i++; &  }&
  do循环基本跟等价于上面的形式(当@array是空的时候,将会有一个警告信息):
  my&$i&=&0; &  do&{ &  &&&&print&$i,&&:&&,&$array[$i]; &  &&&&$i++; &  }&while&($i&&scalar&@array); &
  my&$i&=&0; &  do&{ &  &&&&print&$i,&&:&&,&$array[$i]; &  &&&&$i++; &  }&until&($i&&=&scalar&@array);&
  基本的C风格循环同样有效。注意,我们如何把一个my变量放在for语句中,这是通过在循环范围内定义变量$i实现的:
  for(my&$i&=&0;&$i&&scalar&@&$i++)&{ &  &&&&print&$i,&&:&&,&$array[$i]; &  } &  #&$i&has&ceased&to&exist&here,&which&is&much&tidier.&
  for循环被认为是古老的形式,并且尽可能避免使用。原生的列表迭代更美观。注意:和PHP不一样,for和foreach关键字是同义词。我们只用更容易阅读的方式:
  foreach&my&$string&(&@array&)&{ &  &&&&print&$ &  }&
  如果你需要索引, range operator可以创建一个匿名整型列表:
  foreach&my&$i&(&0&..&$#array&)&{ &  &&&&print&$i,&&:&&,&$array[$i]; &  }&
  你不能去迭代一个哈希变量。但是,你可以迭代它的键值。使用keys内置函数,获取哈希变量的所有键值数组。然后使用foreach方法,就像数组一样:
  foreach&my&$key&(keys&%scientists)&{ &  &&&&print&$key,&&:&&,&$scientists{$key}; &  }&
  因为哈希变量没有顺序,键值可能以任何顺序被返回。使用sort内置函数对键值数组排序,按照字母表从小到大的方式:
  foreach&my&$key&(sort&keys&%scientists)&{ &  &&&&print&$key,&&:&&,&$scientists{$key}; &  }&
  如果使用默认的迭代,你只能在循环内部放置一条语句,你可以使用超级短的循环语法:
  print&$_&foreach&@&
  循环控制
  next和last可以用来控制循环的进度。在大部分的编程语言中,就如continue和break。我们可选择性的为任何循环提供标签。一般约定,标签使用大写字母。在标记了循环后,next和last就可以以标签为目的做跳转。以下的例子,查找100以下的素数:
  CANDIDATE:&for&my&$candidate&(&2&..&100&)&{ &  &&&&for&my&$divisor&(&2&..&sqrt&$candidate&)&{ &  &&&&&&&&next&CANDIDATE&if&$candidate&%&$divisor&==&0; &  &&&&} &  &&&&print&$candidate.&&is&prime\n&; &
  数组相关函数
  在数组中修改
  我们会使用@stack来演示这些:
  my&@stack&=&(&Fred&,&&Eileen&,&&Denise&,&&Charlie&); &  print&@&#&&FredEileenDeniseCharlie&&
  pop  取出并返回数组的最后一个元素。这可以被认作是栈顶:
  print&pop&@&#&&Charlie& &  print&@&&&&&#&&FredEileenDenise&&
  push 追加额外的元素到数组末尾:
  push&@stack,&&Bob&,&&Alice&; &  print&@&#&&FredEileenDeniseBobAlice&&
  shift 取出并返回数组的第一个元素:
  print&shift&@&#&&Fred& &  print&@&&&&&&&#&&EileenDeniseBobAlice&&
  unshift 插入一个新元素到数组开头:
  unshift&@stack,&&Hank&,&&Grace&; &  print&@&#&&HankGraceEileenDeniseBobAlice&&
  pop,push,shift and unshift是 splice(拼接)的特殊情况。splice删除并返回一个数组片段,用一个不同的数组片段代替它:
  print&splice(@stack,&1,&4,&&&&&&,&&&&&&);&#&&GraceEileenDeniseBob& &  print&@&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#&&Hank&&&&&&Alice&&
  从已存在的数组创建新的数组
  Perl提供下面的函数,从现有的数组创建新的数组。
  join函数可以把多个字符串连接在成一个:
  my&@elements&=&(&Antimony&,&&Arsenic&,&&Aluminum&,&&Selenium&); &  print&@&&&&&&&&&&&&&#&&AntimonyArsenicAluminumSelenium& &  print&&@elements&;&&&&&&&&&&&#&&Antimony&Arsenic&Aluminum&Selenium& &  print&join(&,&&,&@elements);&#&&Antimony,&Arsenic,&Aluminum,&Selenium&&
  在列表上下文中,reverse函数返回反序的列表。在标量上下文中,reverse函数把列表的元素串接起来,把它当做一个词倒转返回。
  print&reverse(&Hello&,&&World&);&&&&&&&&#&&WorldHello& &  print&reverse(&HelloWorld&);&&&&&&&&&&&&#&&HelloWorld& &  print&scalar&reverse(&HelloWorld&);&&&&&#&&dlroWolleH& &  print&scalar&reverse(&Hello&,&&World&);&#&&dlroWolleH&&
  map函数接受数组作为输入,并对列表中每一个标量$_进行操作。然后创建一个新的数组。这里的操作通过花括号中以一个表达式的形式提供:
  my&@capitals&=&(&Baton&Rouge&,&&Indianapolis&,&&Columbus&,&&Montgomery&,&&Helena&,&&Denver&,&&Boise&); &  print&join&&,&&,&map&{&uc&$_&}&@ &  #&&BATON&ROUGE,&INDIANAPOLIS,&COLUMBUS,&MONTGOMERY,&HELENA,&DENVER,&BOISE&&
  grep函数接受一个数组作为输入,并返回一个经过滤的数组作为输出。语法跟map很相似。这一次,第二个参数是对输入数组中每一个标量$_进行计算。如果一个布尔值true被返回,标量将会放到输出数组,否则就会过滤掉:
  print&join&&,&&,&grep&{&length&$_&==&6&}&@ &  #&&Helena,&Denver&&
  很明显,结果数组就是成功匹配的元素,这意味这你可以使用grep快速的判断一个数组是否包含某个元素:
  print&scalar&grep&{&$_&eq&&Columbus&&}&@&#&&1&&
  grep和map可以以 list comprehensions 的形式结合,一个异常强大的功能在其他语言是不具备的。
  默认情况下,sort函数返回输入数组,并以单词顺序(字母顺序)排序:
  my&@elevations&=&(19,&1,&2,&100,&3,&98,&100,&1056); &  print&join&&,&&,&sort&@ &  #&&1,&100,&100,&,&3,&98&&
  但是,与grep和map类似,你可以提供你自己的代码来进行排序。Sorting一般是通过一系列的两个元素间的比较来完成的。你的代码获取$a和$b输入,如果$a&小于&$b,则返回-1,如果&相等&则返回0,如果&大于&则返回1
  cmp操作符就是对字符串完成这样的功能:
  print&join&&,&&,&sort&{&$a&cmp&$b&}&@ &  #&&1,&100,&100,&,&3,&98&&
  &飞船操作符&&=&则是对数字实现这样的功能:
  print&join&&,&&,&sort&{&$a&&=&&$b&}&@ &  #&&1,&2,&3,&19,&98,&100,&100,&1056&&
  $a和$b通常是标量,但是可能指向十分复杂的对象,以至于不能轻易做比较。如果你需要更多的空间来做比较运算,你可以创建一个独立的子过程并以它的名字作替代:
  sub&comparator&{ &  &&&&#&lots&of&code... &  &&&&#&return&-1,&0&or&1 &  } &  print&join&&,&&,&sort&comparator&@&
  你不能在grep或者map操作中这样做。
  注意子过程和代码块从来没有显式的提供$a和$b.就像$_, $a 和$b,事实上,一对全局变量被广泛运用于每次比较当中。
  内置函数
  目前位置,你已经看到很多内置函数:print,sort,map,grep,keys,scalar等等。内置函数是Perl的强大武器之一。它们:
  &量很大
  &非常有用
  &拥有大量的文档
  &在不同的语法中会有很大差异,所以请查阅文档
  &有时候接受正则表达式作为参数
  &有时候接受整个代码块作为参数
  &有时候在参数之间不需要逗号
  &有时候需要随意个数的逗号来分隔参数,有时候又不需要
  &有时候可以自动匹配变量,如果只提供了很少一部分变量
  &通常不需要使用括号包围参数,除非在模糊的语义环境中
  对于内置函数,最好的建议是知道它们的存在。抛开文档,直到以后有需要才去查阅。如果你的任务跟它的低层次和足够的通用,就如它之前完成了多次一样,那么机会就是它所拥有的。
  用户定义子程序
  子程序通过sub关键字定义。跟内置函数作对比,用户定义子程序通常接受同样的输入:一个包含标量的列表。列表可以只包含一个元素,或者是空的。一个标量被看做只包含一个元素的列表。带有N个元素的哈希变量被看做2N个元素的列表。
  虽然括号是可选的,子程序通常通过括号被调用,甚至没有任何参数。这样可以清楚的看到一个子程序被调用。
  当你在一个子程序里面,参数可以使用&内置 array变量@_来访问,例如:
  sub&hyphenate&{ &  &&#&Extract&the&first&argument&from&the&array,&ignore&everything&else &  &&my&$word&=&shift&@_; &  &&#&An&overly&clever&list&comprehension &  &&$word&=&join&&-&,&map&{&substr&$word,&$_,&1&}&(0&..&(length&$word)&-&1); &  &&return&$ &  } &  print&hyphenate(&exterminate&);&#&&e-x-t-e-r-m-i-n-a-t-e&&
  参数拆包
  有多种方法对@_变量进行拆包,但是有一些比其他更优越。
  例如子程序left_pad通过给定的填充字符来对输入字符作填充操作,长度为给定的长度。(x函数把同一个字符串复制多份并连接为一行)(注意,为了代码简短,这个子程序缺少一些基本的错误检查,例如确保填充字符只有一个字符,检查给定的长度要大于或者等于现在字符串的长度,对参数作所有必须的检查)
  left_pad可以通过如下方式被调用:
  print&left_pad(&hello&,&10,&&+&);&#&&+++++hello&&
  1.有些人不对参数进行拆包,而只是简单使用@_.这是错误并不被鼓励的。
  sub&left_pad&{ &  &&&&my&$newString&=&($_[2]&x&($_[1]&-&length&$_[0]))&.&$_[0]; &  &&&&return&$newS &  } &
  2.以下对@_的拆包方法,略低于强烈劝阻:
  sub&left_pad&{ &  &&&&my&$oldString&=&$_[0]; &  &&&&my&$width&&&&&=&$_[1]; &  &&&&my&$padChar&&&=&$_[2]; &  &&&&my&$newString&=&($padChar&x&($width&-&length&$oldString))&.&$oldS &  &&&&return&$newS &  } &
  3.通过使用shift删除数据来对@_拆包,这种方法对4个参数的时候推荐使用
  sub&left_pad&{ &  &&&&my&$oldString&=&shift&@_; &  &&&&my&$width&&&&&=&shift&@_; &  &&&&my&$padChar&&&=&shift&@_; &  &&&&my&$newString&=&($padChar&x&($width&-&length&$oldString))&.&$oldS &  &&&&return&$newS &  } &
  如果没有数组提供给shift函数,那么它隐式的对@_进行操作。这种方法很常见:
  sub&left_pad&{ &  &&&&my&$oldString&=& &  &&&&my&$width&&&&&=& &  &&&&my&$padChar&&&=& &  &&&&my&$newString&=&($padChar&x&($width&-&length&$oldString))&.&$oldS &  &&&&return&$newS &  } &
  超过4个参数的情况,就很难跟踪什么在哪里被赋予了值。
  4.你可以同时使用多个标量赋值,对@_整体进行拆包。同样,这对于4个参数的情况才可行:
  sub&left_pad&{ &  &&&&my&($oldString,&$width,&$padChar)&=&@_; &  &&&&my&$newString&=&($padChar&x&($width&-&length&$oldString))&.&$oldS &  &&&&return&$newS &  } &
  5.对于带有很多个参数的子程序,或者某些参数是可选的,或者不能被用于和其他组合,最好的方法是需要用户在调用函数的时候,提供一个参数的哈希变量。对于这种方法,我们的子程序被调用的时候会有点不一样:
  print&left_pad(&oldString&&=&&&pod&,&&width&&=&&10,&&padChar&&=&&&+&); &
  子程序如下:
  sub&left_pad&{ &  &&&&my&%args&=&@_; &  &&&&my&$newString&=&($args{&padChar&}&x&($args{&width&}&-&length&$args{&oldString&}))&.&$args{&oldString&}; &  &&&&return&$newS &  } &
  返回值
  就如其他Perl表达式,调用子程序也会在不同上下文中有不同的行为。你可以使用wantarray函数(也可以叫做wantlist)来检测子程序处于什么上下文当中,并返回一个合适的结果到上下文:
  sub&contextualSubroutine&{ &  &&&&#&Caller&wants&a&list.&Return&a&list &  &&&&return&(&Everest&,&&K2&,&&Etna&)&if& &  &&&&#&Caller&wants&a&scalar.&Return&a&scalar &  &&&&return&3; &  } &  my&@array&=&contextualSubroutine(); &  print&@&#&&EverestK2Etna& &  my&$scalar&=&contextualSubroutine(); &  print&$&#&&3&&
  系统调用
  请原谅,如果你已经直到下面的跟Perl无关的事实。在windows或者linux(我假设,在大部分的其他系统)一个进程每次完成的时候,它就会总结16位的status word。高8位由返回代码(0到255)组成,0一般代表没有正确完成,其他值代表不同的错误程度。剩下的8为很少被检查 && 它们&反应的是错误的模式,就如终止信号和内核信息&。
  你可以在一个Perl脚本中,按照你的选择(从0到255)使用exit退出。
  Perl提供不止一种信号调用方法 - spwan一个子进程,暂停当前的脚本,直到子进程完成为止,然后恢复解释当前脚本。不管使用哪个方法,之后你会发现,内置scalar变量$?已经被赋值为子进程结束时返回的状态。你可以使用$? && 8 语句获取16位代码的高8位返回代码.
  system函数可以用于调用其他程序,并附带参数。system的返回值和$?返回的是同样的值:
  my&$rc&=&system&&perl&,&&anotherscript.pl&,&&foo&,&&bar&,&&baz&; &  $rc&&&=&8; &  print&$&#&&37&&
  另外,你可以使用反引号``来运行命令,并从命令获取标准输出。在标量上下文中,整个输出是以一个字符串的形式被返回。在列表上下文,整个输出则是以字符串的数组被返回,每一个元素代表一行输出。
  my&$text&=&`perl&anotherscript.pl&foo&bar&baz`; &  print&$&#&&foobarbaz&&
  以下是包含其他.pl脚本的时候将会看到的情况,例如:
  use& &  use& &  print&@ARGV; &  exit&37;&
  文件和文件句柄
  标量变量可能包含一个文件句柄,而不是数字/字符串/引用或者是undef。文件句柄实际上是一个特定文件的特定地址的引用。
  使用open函数把标量变量转换为文件句柄。open必须提供一个模式。模式 & 表示我们是希望打开这个文件并从中读取数据:
  my&$f&=&&text.txt&; &  my&$result&=&open&my&$fh,&&&&,&$f; &  if(!$result)&{&die&&Couldn't&open&'&.$f.&'&for&reading&because:&&.$!; &  }&
  如果成功,open返回一个true的值。否则,返回false和通过内置变量$!返回一条错误消息。就如上面看到的,你必须检查open操作是否成功。这种检查十分乏味,一种常见的习惯写法是:
  open(my&$fh,&&&&,&$f)&||&die&&Couldn't&open&'&.$f.&'&for&reading&because:&&.$!;&
  请注意,需要用括号包含open调用的参数。
  从一个文件句柄中读取一行文本,使用readline内置函数。readline返回一整行的文本,并在最后附加一个换行符(除非是文件的最后一行),或者当你读取到文件末尾的时候,则返回undef。
  while(1)&{ &  &&&&my&$line&=&readline&$ &  &&&&last&unless&defined&$ &  &&&&#&process&the&line... &  }&
  使用 chomp去除换行符:
  chomp&$&
  请注意,chomp会直接操作$line变量,所以$line = chomp $line并非你想要的结果。
  你可以使用eof来检测是否已经到达文件末尾。
  while(!eof&$fh)&{ &  &&&&my&$line&=&readline&$ &  &&&&#&process&$line... &  }&
  但是要知道,只需要使用while(my $line = readline $fh),因为if $line返回的是&0&,循环会早早的结束。如果你希望这样写,Perl提供&&操作符,以安全的形式包含readline。这很常见,并且十分安全:
  while(my&$line&=&&$fh&)&{ &  &&&&#&process&$line... &  }&
  甚至是:
  while(&$fh&)&{ &  &&&&#&process&$_... &  }&
  如果需要写一个文件的话,那么打开文件的时候要用不同的模式。模式 & 表示我们希望打开文件并对它进行写操作(& 可能会跟已经存在的文件,并有文件内容的情况发生冲突)然后,只需把文件句柄提供给print函数,就像零参数的形式。
  open(my&$fh2,&&&&,&$f)&||&die&&Couldn't&open&'&.$f.&'&for&writing&because:&&.$!; &  print&$fh2&&The&eagles&have&left&the&nest&;&
  请注意,$fh2和另外一个参数之间没有逗号。
  文件句柄会在它们没有引用的时候自动关闭,但是除此之外:
  close&$fh2; &  close&$&
  3个文件句柄会议全局常量的形式存在:STDIN, STDOUT和STDERR。它们会在脚本开始的时候,自动open。读取用户的输入:
  my&$line&=&&STDIN&; &
  等待用户的输入回车:
  &STDIN&;&
  调用&&而没有文件句柄的时候,会从STDIN读取数据,或者当Perl脚本被调用的时候,参数指定的其他文件中读取数据。
  print会默认输出到STDOUT,如果没有指定具体的文件句柄。
  文件测试
  函数-e是一个内置函数,测试文件是否存在。
  print&&what&&unless&-e&&/usr/bin/perl&;&
  函数-d则是一个内置函数,测试指定的文件是否是一个目录。
  函数-f测试给定的文件是否是一个文本文件。
  这是a large class of functions中的三个函数,以-X 的形式,X是小写或者大写字母。这些函数被叫做文件测试。请注意,前缀的减号。在google查询中,减号表示排除这种样式的结果。这样导致文件测试很难在Google中搜索相关资料。所以可以用&perl file test&作为关键字替代。
  正则表达式
  正则表达式在很多语言中都会出现,并且是一个工具。Perl核心的正则表达式语法跟其他语言基本一样,但是Perl的完整正则表达式的能力则十分复杂和难以理解。我能给你的最好建议就是尽量避免使用复杂的形式。
  通过=~ m//实现匹配操作。在标量上下文中,=~ m//如果成功则返回true,失败则返回false。
  my&$string&=&&Hello&world&; &  if($string&=~&m/(\w+)\s+(\w+)/)&{ &  &&&&print&&success&; &  }&
  括号里面执行子匹配。当完成了一个成功的匹配操作后,子匹配则通过$1, $2, $3, ....返回值。
  print&$1;&#&&Hello& &  print&$2;&#&&world&&
  在列表上下文中,=~ m//则以列表的形式返回$1, $2...
  my&$string&=&&colourless&green&ideas&sleep&furiously&; &  my&@matches&=&$string&=~&m/(\w+)\s+((\w+)\s+(\w+))\s+(\w+)\s+(\w+)/; &  print&join&&,&&,&map&{&&'&.$_.&'&&}&@ &  #&prints&&'colourless',&'green&ideas',&'green',&'ideas',&'sleep',&'furiously'&&
  替代操作通过 = ~ s///完成。
  my&$string&=&&Good&morning&world&; &  $string&=~&s/world/Vietnam/; &  print&$&#&&Good&morning&Vietnam&&
  注意$string的内容是如何被修改的。你需要传递一个标量参数给 =~s///操作符的左边。如果你传递了一个字符串,你得到的就是一个错误。
  /g标签标识&组匹配&。
  在标量上下文中,每一个 =~ m//g 调用在完成一个匹配后继续查找下一个匹配,成功则返回true,失败返回false。你可以访问$1和其他后续变量,和平常一样。例如:
  my&$string&=&&a&tonne&of&feathers&or&a&tonne&of&bricks&; &  while($string&=~&m/(\w+)/g)&{ &  &&print&&'&.$1.&'\n&; &  }&
  在列表上下文中, =~m//g一次过返回所有的匹配。
  my&@matches&=&$string&=~&m/(\w+)/g; &  print&join&&,&&,&map&{&&'&.$_.&'&&}&@&
  =~s///g调用实现全局的搜索/替代操作,并返回成功匹配的个数。下面,我们使用&r&替代所有的元音。
  #&Try&once&without&/g. &  $string&=~&s/[aeiou]/r/; &  print&$&#&&r&tonne&of&feathers&or&a&tonne&of&bricks& &  #&Once&more. &  $string&=~&s/[aeiou]/r/; &  print&$&#&&r&trnne&of&feathers&or&a&tonne&of&bricks& &  #&And&do&all&the&rest&using&/g &  $string&=~&s/[aeiou]/r/g; &  print&$string,&&\n&;&#&&r&trnnr&rf&frrthrrs&rr&r&trnnr&rf&brrcks& &
  /i 标签表示匹配/替代对大小写敏感。
  /x 标签允许你的正则表达式包含空格(例如,换行符)和注释。
  &Hello&world&&=~&m/ &  &&(\w+)&#&one&or&more&word&characters &  &&[&]&&&#&single&literal&space,&stored&inside&a&character&class &  &&world&#&literal&&world& &  /x; &  #&returns&true&
  模块和包
  模块和包在Perl是不一样的。
  模块是一个.pm文件,可以在其他Perl文件(脚本或者模块)中引用。模块是一个文本文件,和perl脚本.pl的语法一模一样。模块的例子可以参考C:\foo\bar\baz\Demo\StringUtils.pm或者/foo/bar/baz/Demo/StringUtils.pm,代码如下:
  use& &  use& &  sub&zombify&{ &  &&&&my&$word&=&shift&@_; &  &&&&$word&=~&s/[aeiou]/r/g; &  &&&&return&$ &  } &  return&1;&
  因为当一个模块被载入时,模块是从头到尾的执行,你需要在末尾返回一个true值,表示这个模块已经载入成功。
  为了让Perl解释器可以找到它们,在调用perl之前,包含perl模块的目录必须在环境变量PERL5LIB中列明。列出包含模块的根目录,而不要列出模块所在目录或者模块本身:
  set&PERL5LIB=C:\foo\bar\%PERL5LIB% &
  export&PERL5LIB=/foo/bar/baz:$PERL5LIB&
  一旦Perl模块被创建,perl就会知道哪里才能找到它们,你可以在perl脚本中使用 require函数搜索并执行它。例如,调用require Demo::StringUtils会触发Perl解释器在PERL5LIB的目录中逐一搜索,查找名为Demo/StringUtils.pm的文件。模块被执行完后,模块中定义的子程序现在对于主脚本来说就是可调用的了。我们的例子中可能叫做main.pl,并且代码如下:
  use& &  use& &  require&Demo::StringU &  print&zombify(&i&want&brains&);&#&&r&wrnt&brrrns&&
  注意,使用双冒号隔开目录和模块。
  现在出现一个问题:如果main.pl包含很多require语句,并且每个模块包含很多require,那么我们就很难去追踪原始的zombify定义到底是在哪里。解决方法就是使用包。
  包是一个命名空间,在里面可以定义子程序。任何你定义的子程序都隐式定义在当前包中。在开始执行时候,你所在的包是main包,但是你可以使用package函数切换包。
  use& &  use& &  sub&subroutine&{ &  &&&&print&&universe&; &  } &  package&Food::P &  #&no&collision: &  sub&subroutine&{ &  &&&&print&&kingedward&; &  }&
  注意,使用双引号作为命名空间的分隔符。
  当你调用子程序的时候,那你隐式的调用了当前包下的对应子程序。另外,你可以显示的指明一个包。看看上面的脚本继续执行会有什么结果:
  subroutine();&&&&&&&&&&&&&&&&&#&&kingedward& &  main::subroutine();&&&&&&&&&&&#&&universe& &  Food::Potatoes::subroutine();&#&&kingedward&&
  上面问题的逻辑解决方法是C:\foo\bar\baz\Demo\StringUtils.pm或者/foo/bar/baz/Demo/StringUtils.pm:
  use& &  use&package&Demo::StringUsub&zombify&{ &  &&&&my&$word&=&shift&@_; &  &&&&$word&=~&s/[aeiou]/r/g; &  &&&&return&$ &  } &  return&1; &
  并且修改main.pl:
  use& &  use& &  require&Demo::StringU &  printDemo::StringUtils::zombify(&i&want&brains&);&#&&r&wrnt&brrrns&&
  现在,细心的阅读下面的内容。
  包和模块是中完全独立和Perl中不同的特性。它们都是使用双冒号作为分隔符。在一个脚本或者模块中可以多次切换包,并且可以在多个位置和多个文件中使用同样的包定义。调用require Foo::Bar并不会查找和载入一个包含Foo::Bar包定义的文件,也不需要载入Foo::Bar命名空间内的子程序。调用require Foo::Bar只会载入一个名为Foo/Bar.pm的文件,并且不一定要在文件内部定义任何的包,实际上,可能在里面是定义了Baz::Qux和其他不相关的包。
  同样,一个子程序调用Baz::Qux::processThis()并不一定是定义在名为Baz/Qux.pm的文件里面。它可以在任何地方被定义。
  区分这俩个概念,是perl中最愚蠢的特性,并且把它们看作不同的不变的概念会导致混乱,和令人发狂的代码。幸好,大部分perl程序员遵循以下两条规则:
  1.perl脚本(.pl)必须不能包含包的声明
  2.perl模块(.pm)必须只能声明一个包,并且对应模块的名字和位置。例如&moduleDemo/StringUtils.pm必须以Demo::StringUtils包名开始。
  因为这两条规则,在实际操作中,你会发现可信的第三方提供的包和模块,可以被认为可以互换的。但是,有一点很重要,你不能把这当成理所当然的,因为你某天可能会碰到一个疯子写的代码。
  面向对象的Perl
  perl并非是一个非常好的面向对象语言。perl的面向对象能力事实上是被嫁接的,以下将说明:
  对象是一个引用(例如标量变量),为了知道它是属于哪个类。为了声明引用是属于哪个类,可以使用bless函数. 为了找出引用的指向是属于哪个类,可以使用ref.
  方法是一个子程序,并以对象(或者,对于类方法,就是一个包名)作为它的第一个参数。对象方法通过使用$obj-&method()调用;类方法通过使用Package::Name-&method()调用。
  类就是一个包含方法的包。
  通过一个简单的例子,就很容易明白。Animal.pm模块包含类Animal:
  use& &  use& &  package&A &  sub&eat&{ &  &&&&#&First&argument&is&always&the&object&to&act&upon. &  &&&&my&$self&=&shift&@_; &  &&&&foreach&my&$food&(&@_&)&{ &  &&&&&&&&if($self-&can_eat($food))&{ &  &&&&&&&&&&&&print&&Eating&&,&$ &  &&&&&&&&}&else&{ &  &&&&&&&&&&&&print&&Can't&eat&&,&$ &  &&&&&&&&} &  &&&&} &  } &  #&For&the&sake&of&argument,&assume&an&Animal&can&eat&anything. &  sub&can_eat&{ &  &&&&return&1; &  } &  return&1;&
  我们可以这样使用这个类:
  require&A &  my&$animal&=&{ &  &&&&&legs&&&&=&&4, &  &&&&&colour&&=&&&brown&, &  };&&&&&&&&&&&&&&&&&&&&&&&#&$animal&is&an&ordinary&hash&reference &  print&ref&$&&&&&&&#&&HASH& &  bless&$animal,&&Animal&;&#&now&it&is&an&object&of&class&&Animal& &  print&ref&$&&&&&&&#&&Animal&&
  注意:几乎任何引用都可以指向任何类。这完全由你决定:(1)引用作为类的实例来使用,还有(2)类必须存在且已经被载入。
  你仍能使用原来的哈希变量
  print&&Animal&has&&,&$animal-&{&legs&},&&&leg(s)&;&
  但是,你还可以通过-&操作符调用对象的方法:
  $animal-&eat(&insects&,&&curry&,&&eucalyptus&);&
  这个调用等价于Animal::eat($animal, &insects&, &curry&, &eucalyptus&).
  构造函数
  构造函数是一个类的方法,返回一个新的对象。如果你需要创建一个,只需要定义即可。你可以使用任何的名称。对于类方法,第一个参数不是对象而是类的名字。在这个例子中,就是&Animal&:
  use& &  use& &  package&A &  sub&new&{ &  &&&&my&$class&=&shift&@_; &  &&&&return&bless&{&&legs&&=&&4,&&colour&&=&&&brown&&},&$ &  } &  #&...etc. &
  通过如下方式使用:
  my&$animal&=&Animal-&new();&
  要创建一个继承自父类的类,则需要使用parent。让我们假设我们的子类叫AnimalwithKoala,在Koala.pm文件里面:
  use& &  use& &  package&K &  #&Inherit&from&Animal &  use&parent&(&Animal&); &  #&Override&one&method &  sub&can_eat&{ &  &&&&my&$self&=&shift&@_;&#&Not&used.&You&could&just&put&&shift&@_;&&here &  &&&&my&$food&=&shift&@_; &  &&&&return&$food&eq&&eucalyptus&; &  } &  return&1; &
  样例代码:
  use& &  use& &  require&K &  my&$koala&=&Koala-&new(); &  $koala-&eat(&insects&,&&curry&,&&eucalyptus&);&#&eat&only&the&eucalyptus&
  最后的方法尝试调用Koala::eat($koala, &insects&, &curry&, &eucalyptus&), 但是有一个子程序eat()并没有在Koala包中定义。然而,因为Koala有一个父类Animal,Perl解释器尝试调用Animal::eat($koala, &insects&, &curry&, &eucalyptus&)来代替,而这个可以正常工作。注意Animal类是如何自动通过Koala.pm载入的。
  因为使用了parent接受了一系列的父类名称,perl支持多继承,这样有利有弊。
  BEGIN语句块
  BEGIN语句块在perl完成解析该块的时候被执行,甚至在文件其他代码被解析之前。在执行的时候会被忽略:
  use& &  use& &  print&&This&gets&printed&second&; &  BEGIN&{ &  &&&&print&&This&gets&printed&first&; &  } &  print&&This&gets&printed&third&;&
  BEGIN块一般首先被执行。你可以创建多个BEGIN块(但是最好不要),它们被从头到尾的执行。BEGIN块通常被第一个执行即使它是在脚本的中间(但不要这样做)或者在最后(也不要这样做)。不要把它混在正常代码里面。吧BEGIN块放在开头!
  BEGIN块会在该块被解析的时候就执行。当完成后,解析会回到BEGIN块末尾继续往下解析。只有当整个脚本或者模块被解析后,BEGIN块之外的代码就会被执行。
  use& &  use& &  print&&This&'print'&statement&gets&parsed&successfully&but&never&executed&; &  BEGIN&{ &  &&&&print&&This&gets&printed&first&; &  } &  print&&This,&also,&is&parsed&successfully&but&never&executed&; &  ...because&e4h8v3oitv8h4o8gch3o84c3&there&is&a&huge&parsing&error&down&here.&
  因为它们在编译的时候就会被执行,BEGIN块放在条件块里面也会首先被执行,即使条件判断是false,不管条件判断是否被执行,实际上永远不会去判断:
  if(0)&{ &  &&&&BEGIN&{ &  &&&&&&&&print&&This&will&definitely&get&printed&; &  &&&&} &  &&&&print&&Even&though&this&won't&; &  }&
  不要把BEGIN块放在条件判断语句内。如果你要在某些条件下才执行,你需要把条件判断放在BEGIN块里面:
  BEGIN&{ &  &&&&if($condition)&{ &  &&&&&&&&#&etc. &  &&&&} &  }&
  现在,你已经知道迟钝的行为和包的语义,模块,类方法和BEGIN块。现在可以解释经常看到的use函数。
  以下3个语句:
  use&Caterpillar&(&crawl&,&&pupate&); &  use&Caterpillar&(); &  use&C&
  跟下面是等价的:
  BEGIN&{ &  &&&&require&C &  &&&&Caterpillar-&import(&crawl&,&&pupate&); &  } &  BEGIN&{ &  &&&&require&C &  } &  BEGIN&{ &  &&&&require&C &  &&&&Caterpillar-&import(); &  }&
  &三个例子并不是顺序有误。这只是因为Perl沉默的
  &use调用实际是BEGIN块的伪装。使用use语句同样要放在文件的头部,不要放在条件判断语句里面。
  &import()并不是一个内置perl函数。它是一个用户定义的类方法。这个由程序员在Caterpillar包中定义或者继承import(),并且这个方法理论上接受任何淡出,并使用这些参数做任何操作。参阅Caterpillar.pm的文档看看实际会发生什么。
  &注意require Caterpillar是如何载入一个名为Caterpillar.pm的模块,而Caterpillar-&import()调用Caterpillar包中定义的import()子程序。希望模块和包是一致的。
  Exporter
  最常见的定义import()方法的途径是继承Exporter模块。Exporter是一个核心模块,和在Perl编程语言中的一个de facto&核心功能。在Exporter的对import实现中,你传递该它的参数列表被翻译为一个子程序名字的列表。当以恶搞子程序被imoprt进去,它在当前包和原来的包都是可用的。
  通过例子,就很容易理解这个概念。以下是Caterpillar.pm的代码:
  use& &  use& &  package&C &  #&Inherit&from&Exporter &  use&parent&(&Exporter&); &  sub&crawl&&{&print&&inch&inch&;&&&} &  sub&eat&&&&{&print&&chomp&chomp&;&} &  sub&pupate&{&print&&bloop&bloop&;&} &  our&@EXPORT_OK&=&(&crawl&,&&eat&); &  return&1; &
  包变量@EXPORT_OK必须包含一个子程序名字的列表.
  另外的代码使用import()通过子程序的名字载入它们,一般使用use语句。
  use& &  use& &  use&Caterpillar&(&crawl&); &  crawl();&#&&inch&inch& &
  在这个例子中,当前包是main, 所以crawl()调用实际是调用main::crawl(), 并映射到(因为它已经被import进来了)Caterpillar::crawl().
  注意: 不管@EXPORT_OK里面的内容是什么, 每一个方法都可以被叫做&longhand&:
  use& &  use& &  use&Caterpillar&();&#&no&subroutines&named,&no&import()&call&made &  #&and&yet... &  Caterpillar::crawl();&&#&&inch&inch& &  Caterpillar::eat();&&&&#&&chomp&chomp& &  Caterpillar::pupate();&#&&bloop&bloop&&
  perl没有私有方法。通常,私有方法以一条或者两条下划线做前缀来命名。
  @EXPORT
  Exporter模块同样定义了一个包变量,叫做@EXPORT,可以使用子程序名字列表来填充。
  use& &  use& &  package&C &  #&Inherit&from&Exporter &  use&parent&(&Exporter&); &  sub&crawl&&{&print&&inch&inch&;&&&} &  sub&eat&&&&{&print&&chomp&chomp&;&} &  sub&pupate&{&print&&bloop&bloop&;&} &  our&@EXPORT&=&(&crawl&,&&eat&,&&pupate&); &  return&1;&
  当调用没有变量的import()的时候,@EXPORT里面的子程序名就会被export:
  use& &  use& &  use&C&#&calls&import()&with&no&arguments &  crawl();&&#&&inch&inch& &  eat();&&&&#&&chomp&chomp& &  pupate();&#&&bloop&bloop&&
  但是注意,我们回到这个场景,我们很难区分crawl()实际在哪里被定义的。这有双重意义:
  1.当使用Exporter创建一个模块,不要使用@EXPORT来导出子程序。通常,让用户调用子程序&longhand&或者import()显式的导入进来(使用Caterpillar(&crawl&),这是一个很好的线索去搜索Caterpillar.pm查看crawl()的定义)
  2.当通过Exporter使用模块,通常显式命名需要import的子程序。当你不希望import任何子程序,而是希望参考他们的longhand,你必须显式的提供一个空列表:use Caterpillar ().
  其他要注意的
  核心模块Data::Dumper&可以用于随意输出一个标量到屏幕。这实际是一个调试工具。
  这里有另外一种语法,qw{},定义数组。通常在use语句中看到:
  use&Account&qw{create&open&close&suspend&delete};&
  还有很多其他quote-like操作符
  在=~ m//and=~ s///操作中,你可以使用花括号代替斜杠作为正则表达式的分隔符。当正则表达式包含大量的斜杠,需要转义反斜杠的情况,这种语法十分有用。例如=~ m{///}匹配3个斜杠,还有=~ s{^https?://}{}去掉URL里面的协议名称。
  Perl其实有常量。但是现在不被推荐,但也并不是所有场合都是。常量实际是没有括号的子程序。
  有时候,人们忽略哈希键值的引号,写成$hash{key}代替$hash{&key&}。这样会产生歧义,因为没有括号引用的key值会被当作调用子程序key()
  如果看到一个包裹在双尖括号,例如&&EOF,&没有格式化的语句块,那么google的神奇单词&here-doc&就派上用场。
  注意!很多内置函数可以被调用,并不需指定参数,使它们以$_来代替。希望这个可以让你更好的理解这个格式:
  print&foreach&@&
  foreach&(&@array&)&{ &  &&&&next&unless& &  }&
  我并不喜欢这个格式,因为在重构的时候会有问题。
&&&主编推荐
&&&热门试卷
&&&最新视频
&&&热门阅读
&&&最新问答
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&湘教QS2-164&&增值电信业务经营许可证湘B2-

我要回帖

更多关于 阿拉伯数字字体大全 的文章

 

随机推荐