VERDVANA'S BLOG Verdvana

Perl入门


1 前言

        工作需要,整个Perl玩玩。


2 开发习惯

2.1 内建警告信息

        当程序内有可疑的语句时,内建警告信息可以发出警告提示。添加内建警告信息有四种方式:

  • 在运行时加上“-w”命令行,例如:
      $perl -w hello.pl
    
  • 在程序中指定解释器路径后加上“-w”:
      #! /usr/bin/perl -w
    
  • 对于perl 5.6以及更新的版本,可以在代码中加入“use warnings”,同样作用于整个程序:
      #! /usr/bin/perl
      use warnings
    
  • 只对一段代码内建警告信息,可以在代码前后加入以下指令:
      ……
      use warnings
      ……  # 代码段
      no warnings
    

        如果出现警告,且想看更详细的问题描述,则在程序中加入:

use diagnostics;

        在代码中加入如下指令,会强制终止程序执行,直到warning被解决:

use strict;

        它有如下作用:

  • 避免错误拼写;
  • 限定变量范围。

3 标量

        标量(Scalar)包括数字标量和字符串标量。

  • 标量可以在任意位置随时声明使用;
  • 标量名可以是字母、数字、下划线,区分大小写;
  • 标量的作用域:
    • 包变量:模块情况下为包变量,是包内的全局变量,在整个包及下面的子函数中都可用;
    • 私有变量:
      • my变量:只在本层模块起作用;
      • local变量:在本层和本层下层的函数都可以看到的变量。

        数字标量:

  • 全部为双精度浮点数,有效值为10-100至10100
  • 普通表示法:3.1415926,-50;
  • 科学计数法:2.18e22,5.16E-10;
  • 特殊数字:
    • 较长的、不带小数点的数字,可用下划线分开(好像类似Verilog):3141592639 → 31_4159_2639;
    • 非十进制:
      • 八进制:以0开头,例如0377表示十进制的255;
      • 十六进制:以0x开头,例如0xFF表示十进制的255;
      • 二进制: 以0b开头例如0b1111_1111表示十进制的255;
      • 同样支持下划线隔开。

        字符串标量:

  • 标量值为字符串,由引号标识;
  • 字符串由可输出的字母、数字和标点符号组成;
      $data="hello,world";
    
  • 字符串的引号既可以是双引号也可以是单引号,转义字符只在双引号中有效

4 数组

        数组是标量数据的有序列表,是多个标量数据的一种集合。

4.1 创建数组

  • 可以包含任意多个元素,从0到全部占满内存;
  • 以“@”符号作为标识;
      @hits = (1,6,7);    
      @var  = (10..20);
      @str  = ('a'..'z');         
      @names = ("Apple", "banana", "郭达");
    
  • 同一个数组中的元素可以是数字也可以是字符串,也可以既有数字也有字符串
    • (1,2,3):包含1,2,3三个数的列表;
    • (1,2,3,):包含1,2,3三个数的列表,逗号被省略;
    • (“test”,4.5):包含一个字符和一个数字;
    • ():空列表,零个元素。
    • (1..5):包含1,2,3,4,5,五个元素;
    • (5..1):不能是降序,所以是空列表;
    • (0,2..6,10):包含0,2,3,4,5,6,10七个元素;
    • ($m..$n):如果$m小于$n,则为由$m到$n的数字列表,否则为空列表,
    • qw(str1 str2 str3):纯字符串列表,空格、制表符、换行都可以作为间隔符,等同于(“str1”,”str2”,”str3”),也可用其他任何标点符号作为界定符代替括号,例如qw!str1 str2 str3!。

4.2 特殊赋值

        特殊的数组赋值方法:

  • pop:取出数组中最后一个元素,同时返回该元素值:
      @array=(5..9);      #@array为(5,6,7,8,9)
      $test=pop(@array);  #@array为(5,6,7,8),$test为9
    
  • push:添加一个元素(或一串元素)到数组尾端:
      push(@array,8); #@array的值为(...,8)
    
  • shift:取出数组最左边的元素,同时返回该元素值(与pop类似);
  • unshift:添加一个元素(或一串元素)到数组的始端(与push类似)。

4.3 切割数组

        数组元素的访问:

  • 通过索引对数组元素进行访问:
    • 索引值从0开始;
        $array[0];
      
    • 索引值超出元素数量,返回空元素。
  • 特殊索引值:
    • 最后元素的索引值
        my @array = (1,2,3);
        print "$#array"; #3
      
    • 负数索引:代表最后一个元素
        my @array = (1,2,3);
        print "$array[-1]"; #3
        print "$array[-2]"; #2
      

4.数组大小

        通过scalar打印数组大小:

@array = (1,2,3);
print "数组大小: ",scalar @array,"\n";

        数组长度返回的是数组物理大小,而不是元素个数

@array      = (1,2,3);
$array[50]  = 4;

$size = @array;
$max_index = $#array;

print "数组大小:   $size\n";       #51
print "最大索引:   $max_index\n";  #50

5 引用(指针)

        变量的$符号前加“\”,表示该变量对应的值在内存当中的地址。

        引用方法:

  • 软引用:
    • 类似于软链接,存储一个变量的名字(替代):
      • 如果:$scalar = “Hello”; $refer = “scalar”;
      • 那么:$$refer的实质即$scalar;
  • 硬引用:
    • 类似于硬链接,存储地址:
      • 标量引用:$scalar = \$foo;
      • 常量引用:$constr = \1234.55;
      • 数组引用:$array = \@arr;
      • 匿名数组引用:$arr = [1,2,3,4];
    • 解引用:
      • ${$scalar},简写为:$$scalar;
      • ${$constr},简写为:$$constr;
      • ${$array}[0];
      • ${$scalar}[0]。

6 数据运算

6.1 运算符

        Perl的运算符包括算数、比较、逻辑、位、赋值和其他运算符。

        算术运算时,标量从左往右第一个非数字的值以及后面的值会被抛弃掉。

        数字比较运算符的操作对象是数字值或数字变量。“<=>”用于比较,返回值为“1,0,-1”。

        字符串比较操作符的操作对象是字符串或字符串变量,基于ASCII码的比较:

操作符 含义
gt 大于
ge 大于等于
lt 小于
le 小于等于
eq 等于
ne 不等于
cmp 比较,返回1,0,-1

        逻辑位运算与Verilog类似。

        位运算符与Verilog类似。

        赋值运算符包括:

  • 以等号“=”作为赋值标识,一般的赋值方式是数值拷贝;
  • 包括一些运算和等号一起的省略写法:+=,-=,*=,/=,**=,%=;
  • 另外还有.=,x=等字符串赋值的省略写法。

        自增自减运算符与C语言类似。不过可用于字符串,即对应的ASCII码进行运算。

        其他运算符:

  • 连接运算符:.,被连接的字符串中间不会自动加入空格;
  • 重复运算符:x,后面跟数字n,把字符串重复n次;
  • 逗号连接符:,,其实就是把多句拼成一句;
  • 条件运算符:?:,与Verilog类似。

6.2 运算符优先级

        粗略规则:

  • 单目操作符优先级高于双目操作符;
  • 同等情况下,位运算高于逻辑运算高于赋值运算。

        具体规则:

操作符 结合性 完成的操作
() 改变运算的优先级;列表操作符
-> 引用操作符
++ – ++自增,–自减
** 乘幂
\ ! ~ + - \取地址,!逻辑非,~按位非,+正,-负
=~ !~ =~匹配绑定操作符,!~不匹配绑定操作符
* / % x *乘,/除,%求余,x字符串重复
« » 移位操作符
«= »= lt le gt ge 不等关系运算符
== != <=> eq ne cmp 相等关系运算符
& 按位与
| ^ |按位或,^按位异或
&& 逻辑与
|| 逻辑或
?: 条件操作符
= += x= .= 赋值以及增量赋值操作符
, => 逗号操作符;列表操作符(右结合性)
not 逻辑非
and 逻辑与
or xor or逻辑或,xor逻辑异或

7 控制结构

7.1 if

        单条件:

if(<条件>)  <执行语句>;
if(<条件>)  {
    <执行语句1>;
    <执行语句2>;
};
<执行语句>  if(<条件>);

        多条件:

if(<条件1>)     {
    <执行语句1>;
}
elsif(<条件2>)  {
    <执行语句2>;
}
else            {
    <执行语句3>;
}

7.2 unless

        if的反义。

7.3 for

        与C语言类似,但其中增加了中断、跳跃的使用:

  • next:跳至本次循环的结束位置,开始下一个循环;
  • last:跳至循环的最后位置(退出循环)。

7.4 foreach

        foreach是for循环结构的变体,foreach循环逐个遍历列表中的值,依次迭代。

foreach <列表> (<变量>)
{
    <执行语句>;
}

        如果不想另想foreach那行的列表名称,可以省略,然后在下面使用“$_”默认值来代替:

foreach  (@array)
{
    printf("$_\n");
}

        需要注意的是:

  • foreach取得的元素并非按照先后顺序,而是随机的;
  • 可以使用sort来对元素进行排序然后取出。

7.5 while

        与C语言类似,也加入了“next”和“last”。

7.6 until

        while的反义,通常与continue一起使用:

until(<条件>)
    <执行语句1>;
continue
    <执行语句2>;

        当条件不满足,执行语句1会执行,执行语句2也会执行。当条件满足,执行语句1和2都不再执行。

7.7 switch

        与Verilog类似。


8 正则表达式

8.1 简介

        正则表达式,就是用某种模式去匹配一类字符串的一个公式。

        给定一个正则表达式和另一个字符串,我们可以达到如下目的:

  • 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”);
  • 可以通过正则表达式,从字符串中获取我们想要的特定部分。

8.2 应用

        简单模式:

  • 如果模式匹配的对象是$_,把模式写在斜杠(/)中;
  • 能匹配上时,返回值为1,否则为0;
  • 如果匹配项本身含有斜杠,则使用转义字符反斜杠(\)。
  • 通过“\p{<属性名>}”来进行属性匹配:
    • 匹配空格或换行:
        \p{Space}
      
    • 匹配数字:
        \p{Digit}
      
    • 匹配十六进制:
        \p{Hex}
      
    • 匹配不包含属性:
        \P{<属性>}
      

        模式分组:

  • 利用小括号进行字符串的分组:
      /world+/    #匹配的是"worlddddd..."
    
      /(world+)/    #匹配的是"worldworldworld..."
    
  • 括号、反斜杠、数字编号可以组成捕获组的模式;
  • 括号内的内容作为元字符,用反斜杠后面加数字表示再次匹配:
      /(world)\3/    #匹配的是"worldworldworld"
    

        择一匹配:

  • 使用竖线来表示匹配时候的“或”:
      /Hello|World/       #能匹配任何包含Hello或者World的字符串
      ``````perl
      /Hello(|and)World/  #能匹配任何包含Hello或者World的字符串
    

8.3 元字符

        元字符是一种特殊字符,起通配作用,如果在前面加上反斜杠,则这些元字符就会失去其特殊含义。

        单字符与数字:

元字符 所代表的含义
. 匹配除换行符外的任意字符
[a-z0-9] 匹配集合中任意单个字符
[^a-z0-9] 匹配不在集合中的任意单个字符
\d 匹配单个数字
\D 匹配非数字字符,等效于[^0-9]
\w 匹配数字型(字)字符
\W 匹配非数字行(非字)字符

        空白字符:

元字符 所代表的含义
\s 匹配空白字符,如空格,制表符和换行符
\S 匹配非空白字符
\n 匹配换行符
\r 匹配回车符
\t 匹配制表符
\f 匹配进纸符
\b 匹配退格符
\0 匹配空值字符

        锚定字符:

元字符 所代表的含义
\b 匹配字边界(不在[]中)
\B 匹配非字边界
^ 匹配行首
$ 匹配行尾
\A 匹配字符串开头
\Z 匹配字符串或行的末尾
\z 只匹配字符串的末尾
\G 匹配前一次m//g

        重复字符:

元字符 所代表的含义
x? 匹配0或1个x
x* 匹配0或多个x
x+ 匹配1或多个x
(xyz)+ 匹配1或多个模式xyz
x(m,n) 匹配m到n个x组成的值
   
   

        替换字符:

元字符 所代表的含义    
(was were will) 匹配was、were、will之一(三选一)

        其它字符:

元字符 所代表的含义
\12 匹配八进制数,直到\377
\x811 匹配十六进制数值
\cX 匹配控制字符
\e 匹配ASCII
\x{NUMBER} 匹配以十六进制形式给出的Unicode

        当模式中含有多种元字符时,根据优先级顺序来判断匹配量;

优先级 元字符属性 举例
圆括号 (…),(?:…),(ABC)
| 量词 a*,a+,a?,a{n,m}
| 错位和序列 abc,^,$,\A,\b,\z,\Z
择一竖线 |
原子 a,[a,b,c],\d,\1

        正则表达式的形式:

  • 模式匹配:
    • 得到“是否匹配”的结果;
    • 形式为:
      • m/<regexp>/;
      • m?<regexp>?;
      • /<regexp>/;
    • 同匹配操作符一起,用来判断是否匹配后面的字符串;
    • 匹配的表达式中,括号部分的匹配项用$标号表示;
    • 匹配上返回值为1,否则为0;
    • 模式匹配的选项:

      选项 描述
      g 忽略所有可能的模式
      i 忽略大小写
      m 将串视为多行
      s 将串视为单行
      x 忽略模式中的空白
  • 模式替换:
    • 返回值为布尔量;
    • 形式为:
      • s/<regexp>/<replacement>/;
      • s?<regexp>?<replacement>?;
    • 模式替换的选项:

      选项 描述
      g 忽略所有可能的模式
      i 忽略大小写
      m 将串视为多行
      s 将串视为单行
      x 忽略模式中的空白
      e 替换字符串作为表达式
  • 模式转化:
    • 同模式替换类似,用以弥补模式替换的不足;
    • 形式为:
      • tr/<regexp>\/<replacement>/;
      • tr?<regexp>\?<replacement>?;
    • 将regexp中的字符依次、逐个替换为replacement的字符;
    • 返回值为被替换掉的字符数
    • 特殊功能:
      • 大小写互换:
          $str = ~tr/a-zA-Z/A-Za-z
        
      • 特定字符的计数
          $str = ~tr/0-9/0-9
        
    • 模式替换的选项:

      选项 描述
      c 转化所有未指定字符
      d 删除所有指定字符
      s 多个相同的输出字符缩成一个

        正则表达式的原则:

  • 仅对标量进行匹配(数组不行);
  • 匹配时,默认只匹配/替换一次,且对象为最早被匹配到的;
  • 能够处理双引号所能处理的任意或全部字符;
  • 在求职过程中产生两种情况:结果状态和反向引用;
  • 核心能力在于通配符和多重匹配运算符;
  • 如果匹配不止一个字符合集,可以使用“|”来增加灵活性;
  • 用(?…)语法给正则表达式提供扩展功能。

9 子程序

9.1 基本语法

        子程序的声明:

sub name        ;           ## 声明一个名字为name的子程序

sub name PROTO  ;           ## 声明一个名字为name的子程序,带原型

sub name PROTO ATTRS    ;   ## 声明一个名字为name的子程序,带原型和属性

        子程序的创建(可以不声明直接创建):

sub name BLOCK       ;      ## 声明一个名字为name的子程序,BLOCK为子程序内容

        子程序的基本规则:

  • 定义以“sub”关键字开头,后面接程序名;
  • 子程序体用花括号括起来;
  • 子程序可以在Perl中任何地方定义,或者从外部文件导入;
  • 被传递的参数可以通过Perl的特殊变量@_访问;

9.2 子程序的调用

        直接调用语法:

Name (list)     #函数名、括号和参数列表
Name list       #函数名和参数列表,省略括号的用法适用于先声明后调用
&Name           #&和函数名,适用于先调用后定义

        说明:

  • Perl自带很多函数,都是用大写命名:BEGIN、INIT、DESTORY;
  • 自定义的子程序尽量避免全大写命名;
  • 子程序调用后,会以值的形式返回;
  • 返回值可以为字符串、数字、布尔量、甚至为空;
  • 默认情况下,子程序中最后一个语句的值将用作返回值;
  • 可以使用“return”来指定返回值;
  • 子程序中,“return”之后的语句被忽略;

        参数传递;

  • 标量参数:
    • 默认使用“@_”代表所有子程序的输入参数列表;
    • 传递形式为:
        &sub1($number1,$number2,$number3)
      
        sub sub1{
            my ($number1,$number2,$number3)=@_;
        }
      
  • 数组参数:
    • 与标量参数类似。

        说明:

  • 参数为数组时,子程序只赋值给一个数组变量
  • 子程序中多余的数组变量为空;
  • 变量和数组可以同时传递

9.3 子程序和局部变量

        局部变量:

  • 变量有各自的作用域;
  • 子程序中的变量,作用域一般在当前子程序中;
  • 通过my来识别局部变量的特征。

        子程序间的变量值交互可以通过引用来传递变量。


10 文件处理

10.1 句柄

        Perl通过句柄和“外面的世界”连接。句柄是一个顺序号,对于打开的文件是唯一的识别依据,也是一种特殊的数据类型。

        间接文件句柄:

  • 任何有效的Perl标识符,由大小写字母、数字和下划线组成;
  • 不同于其他变量的是,简介Perl文件句柄没有标志性的前缀;
  • 经常以全部大写字母表示它们;
  • 输入输出句柄:STDIN,STDOUT和STDERR:
    • STDIN:
      • standard input;
      • 默认的输入间接Perl文件句柄;
      • 文件句柄读取的数据取自用户选择的输入设备,通常为键盘,例如:my $data = <STDIN>;
    • STDOUT:
      • standard output;
      • 默认的输出间接Perl文件句柄;
      • 发送给该句柄的数据在用户指定的输出设备上显示,通常为命令窗口,例如:print STDOUT “xxx”;
    • STDERR:
      • standard error;
      • 用于错误信息诊断、调试和其他类似的偶发输出;
      • 默认情况下,与STDOUT使用相同的输出设备;
  • 自定义句柄:
    • 由用户自己指定文件,获取该文件的标识。

10.2 打开文件

        使用open函数打开文件:

  • 语法:
      open(filehandle,"pathname");
    
  • 第一个参数为句柄名;
  • 第二个参数为文件路径。

        使用die函数提示错误和终止程序运行,并输出一条有意义的出错消息。语法为:

open(filehandle,"pathname") || die;

        也可以自定义出错消息:

open(filehandle,"pathname") || die "出错消息";

        使用“$!”得到系统所需要的最后一个操作的出错消息:

open(filehandle,"pathname") || die "出错消息 $!\n";

        warn函数用来发出一个警告而不会终止程序:

if(!open(filehandle,"pathname") ){
    warn "不能读取";
}

        关闭文件句柄:

close(filehandle);

10.3 读写文件

        使用文件输入操作符(尖括号运算符)读入文件;

open(filehandle,"pathname");
$line = <filehandle>
close(filehandle);

        其中:

  • 尖括号运算符读取文件的一行输入;
  • 文件被读完时,返回值为空;
  • 利用循环结构来读取所有数据:
      open(filehandle,"pathname");
      while($_=<filehandle>){
          print $_;
      }
    
  • 通过数组接收所有输入数据:
      open(filehandle,"pathname");
      my @array = <filehandle>;
      print @array;
    

        写入文件语法:

open(filehandle,">pathname");   #覆盖写入
open(filehandle,">>pathname");  #追加写入

        写入具体内容语法:

print filehandle LIST;

        举例:

open(MYFILE,">myfile.txt");   #覆盖写入
print MYFILE "aaa";
my $line = "bbb";
print MYFILE $line;
close(MYFILE);

        Windows对文本文件和二进制文件进行了区分,而Perl并不知道他们之间的差别,因此如需写入二进制数据,使用binmode:

open(MYFILE,"cat.gif"); 
binmode(MYFILE);
print MYFILE "abc";
close(MYFILE);

10.4 文件测试运算符

        测试文件的必要性:

  • 实际的读写速度比较慢;
  • 读写时容易产生错误。

        包含:

运算符 举例 结果
-r -r ‘file’ 可以读取file则返回真
-w -w $a $a中包含的文件名是可以写入的文件名,则返回真
-e -e ‘myfile’ myfile存在则返回真
-z -z ‘data’ data存在,但它是空的,则返回真
-s -s ‘data’ data存在,则返回data的大小
-f -f ‘a.txt’ a.txt是个普通文件,则返回真
-d -d ‘/tmp’ /tmp是个目录,则返回真
-T -T ‘unknow’ unknow是一个文本文件,则返回真
-B -B ‘unknow’ unknow是一个二进制文件,则返回真
-M -M ‘foo’ 返回程序启动运行以来foo文件被修改后经过的时间

11 终端输出颜色

        使用Perl可以在终端打印出彩色字符,前提是需要添加Term::ANSIColor模块。

11.1 使用函数

        使用的模块为:

use Term::ANSIColor;

        这种方式通过color()把任意数量的颜色属性串成一个用空格分隔的字符串并存到变量color里,然后可以用普通的print方法输出彩色字符串。

        输出到color函数中的属性可以是:

clear, reset, dark, bold, underline, underscore, blink, reverse, concealed, black, red, green, yellow, blue, magenta, cyan, white, on_black, on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white

        打印完一句之后要reset,不然当前属性会加在下一次打印的文字上。

        例如:

use Term::ANSIColor;

print color 'bold red';     print "blod red\n";    print color "reset";
print color 'dark red';     print "dark red\n";     print color "reset";
print color 'red';          print "red\n";          print color "reset";

print color 'underscore bold green';        print "green\n";     print color "reset";
print color 'bold reverse yellow';       print "yellow\n";          print color "reset";

        写个脚本展示一下这些颜色和属性,但是一个个码太麻烦了,color后面的属性又不能用变量代替,就写个脚本生成这个脚本好了:

my @color=("black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "on_black", "on_red", "on_green", "on_yellow", "on_blue", "on_magenta", "on_cyan", "on_white");

my $text = "use Term::ANSIColor;
";

foreach(@color){
    $text .= "print color '$_'; print '$_'; print color 'reset';
print color 'bold $_'; print 'bold_$_'; print color 'reset';
print color 'dark $_'; print 'dark_$_'; print color 'reset';
print color 'bold dark $_'; print 'bold_dark_$_'; print color 'reset';
print color 'underline $_'; print 'underline_$_'; print color 'reset';
print color 'reverse $_'; print 'reverse_$_'; print color 'reset';
print \"\\n\";
"
}

open    PL,"> color.pl";
print   PL $text;
close   PL;

system("chmod +x color.pl");
system("perl color.pl");

        运行这个脚本会生成一个名为color.pl的脚本,并且自动运行color.pl,在terminal里打印出各种颜色和属性:

color

11.2 修改属性

        使用的模块为:

use Term::ANSIColor qw(:constants);

        如果使用这种方法,可以直接把颜色属性放在要输出的问题前面,从而简化输出步骤。这些颜色属性有:

CLEAR, RESET, BOLD, DARK, UNDERLINE, UNDERSCORE, BLINK, REVERSE, CONCEALED, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, ON_BLACK, ON_RED, ON_GREEN, ON_YELLOW, ON_BLUE, ON_MAGENTA, ON_CYAN, ON_WHITE

        例如:

use Term::ANSIColor qw(:constants);

print BOLD, BLUE, “bold blue”, RESET;

        如果觉得每次要在末尾加RESET复位颜色属性很麻烦,可以加上如下代码,每次打印完字符,只要属性值之间没有逗号,系统将自动清除掉颜色属性:

$Term::ANSIColor::AUTORESET = 1;

        例如:

use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET = 1;

print BOLD BLUE “bold blue\n”;
print “test\n”;

12 Hash数组

12.1 简介

        Hash是一种数据结构,和数组类似,可以将值(value)存放到其中,或者从中取回值。但和数组不同的是,其索引不是数字而是名字。也就是,索引(key)不是数字而是任意的、唯一的字符串。它们没有确定的顺序,也没有第一个元素。

        key和value均为任意的标量,但key通常转换为字符串。由于Perl的“没有不必要的限制”的设计哲学,Hash可以是任意大小,从空Hash(没有key/value对),到任何你内存允许的大小。key是唯一的,但value可以重复。value可以是数字、字符串、undef,或是它们的混合,但key是唯一的。

12.2 用法

        Hash的建立:

my %hash = ("a"=>1,"b"=>2,"c"=>3);
my %hash = ('a','1','b','2','c','3');

        还可以直接赋值,如果赋值的元素不存在,则被创建,如果赋值的数组从未使用过,也被创建:

my %hash = ("a"=>1,"b"=>2,"c"=>3);
%hash{"d"} = 4; # hash:"a"=>1,"b"=>2,"c"=>3,"d"=>4

12.3 keys/values函数

        keys函数会返回此hash的所有key,values函数将返回所有value,如果hash中没有元素,则此函数将返回空列表。

print my @k = keys %hash;
print my @v = values %hash;

12.4 hash的循环

        利用keys函数的foreach循环语句,这种循环效率比较低,因为每返回一个下标,还得再去寻找其值,如:

  foreach $holder (keys(%records)){
  $record = $records{$holder};
}

        如果想迭代hash的每一个元素,通常使用each函数,它将返回key/value对应的两个元素列表。当对同一个hash函数进行一次迭代时,将返回下一个key/value对,直到所有的元素均被访问。如果没有更多的key/value对,则each函数将返回空表。

my %hash = ("a"=>1,"b"=>2,"c"=>3);
while (($key,$value) = each %hash) {
    print "$key => $value\n";
}

12.5 sort函数

        each返回的key/value对顺序是混乱的,如果像将其按序排放。可以使用sort函数对它们排序。

my %hash = ("a"=>1,"b"=>2,"c"=>3);
foreach $key (sort keys %hash) {
    $value = $hash{$key};
    print "$key => $value\n";
}

12.6 exists函数

        要查看hash中是否存在某个key。可以使用exists函数,如果hash中存在此key,则返回true,与是否有对应的value无关

my %hash = ("a"=>1,"b"=>2,"c"=>3);
if (exists $hash{'a'}) {
    print "ture\n";
}

12.7 delete函数

        delete函数将某个给定的key,以及对应的value从hash中删除。如果不存在这个key,则什么也不做,不会有警告或错误信息

        只能使用delete函数来删除关联数组的元素,不能使用push,pop,shift及splice,因为其元素位置是随机的。

my %hash = ("a"=>1,"b"=>2,"c"=>3);
delete $hash{'a'};
foreach my $key (sort keys %hash){
    my $value = $hash{$key};
    print "$key => $value\n";
}

12.8 数组与hash

        与列表一样,也可以通过数组变量创建hash,其元素数目应该为偶数:

my @array = ("apples",17,"bananas",9,"oranges","none");
my %hash = @array;

        反之也一样,但由于hash顺序未定义,因此赋给数组之后顺序不一定:

my %hash = ("apples",17,"bananas",9,"oranges","none");
my @array = %hash;

        告辞。