Perl入门
26 Jul 2021 12626字 43分 次 Perl打赏作者 CC BY 4.0 (除特别声明或转载文章外)
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];
- 索引值超出元素数量,返回空元素。
- 索引值从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使用相同的输出设备;
- STDIN:
- 自定义句柄:
- 由用户自己指定文件,获取该文件的标识。
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里打印出各种颜色和属性:
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;
告辞。