Perl的数据类型总览
Perl 是一种弱类型语言,所以变量不需要指定类型,Perl 解释器会根据上下文自动选择匹配类型。Perl 有三个基本的数据类型:标量、数组、哈希。
标量(scalar)
标量是Perl语言中最基本的一种数据类型。这种数据类型的变量可以是数字,字符串,浮点数,八进制等,不作严格的区分。在使用时在变量的名字前面加上一个$
表示是标量。如下所示:
|
|
我不是太能理解标量的含义,我猜测可能是因为Perl擅长处理文本,而把一些最基本的符号,例如数字,字符串,浮点数都当作是一个东西,这样比较容易达到目的,毕竟Perl设计的初衷并不是为了处理一些数据。因此对于标量的理解,就把它当作是组成文本的最基本单位就行了。
define函数判断变量的定义
如果未定义变量,那么这个变量就会赋予undef
的值,它不是数字,也不是字符串,有时候也会被当作数字0,使用defined
函数会知道一个变量是否被定义了,如下所示:
|
|
单引号内的字符串
单引号内的字符串直接量指的是一对单引号内的一串字符,这两个单引号并不属于字符串的内容。如果要表示单引号,需要加反斜线进行转义,如下所示:
|
|
双引号内的字符串
双引号可以转义许多字符,或者是用八进制或十六进制写法来表示任何字符,如下所示:
|
|
Perl中的转义字符
转义字符 | 含义 |
---|---|
\\ | 反斜线 |
\’ | 单引号 |
\” | 双引号 |
\a | 系统响铃 |
\b | 退格 |
\f | 换页符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\0nn | 创建八进制格式的数字 |
\xnn | 创建十六进制格式的数字 |
\cX | 控制字符,x可以是任何字符 |
\u | 强制下一个字符为大写 |
\l | 强制下一个字符为小写 |
\U | 强制将所有字符转换为大写 |
\L | 强制将所有的字符转换为小写 |
\Q | 将到\E为止的非单词(non-word)字符加上反斜线 |
\E | 结束\L、\U、\Q |
转义字符的使用案例
|
|
字符串操作
字符串的连接使用点号(.
),如下所示:
|
|
字符串也能做乘法,如下所示:
|
|
运行结果如下所示:
|
|
数字与字符串之间的自动转换
通常Perl会根据需要,自动在数字和字符串之间进行类型转换。这主要取决于操作符,如果操作符(比如+)需要的是数字,Perl就会将操作数视为数字,如果是操作符(比如点号)需要字符串时,Perl便会将操作数视为字符串。因此,你不必担心数字和字符串间的差异,只管合理使用操作符,Perl会自动完成剩下的工作。
对数字进行运算的操作符(例如乘法),如果遇到字符串类型的操作,Perl会自动将字符串转换成等效的十进制浮点数进行运算,例如"12"*"3"
的结果会是36,字符串中非数字的部分(以前前置的空白符号)会被忽略,因此,”12fred34”*”3”也会得到36。完全不含数字的字符串会被转换为零。“前置零”只对直接量有效,不能用于字符串的自动转换,自动转换只能按照十进制数字来处理,例如:
|
|
在进行字符串的操作时(例如使用字符串连接符号)意外得到数字时,为数字就会被转换为形式相的字符串。比如要把字符串Z与“5乘以7的结果”相连接,就如下所示:
|
|
标量变量
Perl中变量是通过前面的符号来区分的,这个符号称为魔符(sigil),变量分为标量变量(用$
来区分),数组变量(用@
来区分),哈希变量(用%
来区分)。
标量变量的赋值
变量不需要声明类型,在变量赋值后,解释器会自动分配匹配的类型空间,变量使用等号(=)来赋值,如下所示:
|
|
借助代码点创建字符
用于编码抽象字符的整数范围叫做代码空间,其中的特殊整数叫做代码点(code point),简单来说,就是处理一些不常见字符的代码。在Perl中,使用代码点,然后使用chr()函数转换为对应的字符,如下所示:
|
|
从结果可以看出,使用代码点可以输出一些特殊字符,结果中还有一些提示信息,提示这些字符是宽字符,先不用管它们。
数组
如果把Perl的标量(scalar)理解为单数(singular),那么Perl里的复数(plural)就是数组与列表。数组是用于存储一个有序的标量值的变量。数组用@
表示,要访问数组的变量,可以使用美元符号($
)+变量名,并指定下标来访问,实例如下所示:
|
|
列表
列表是包含在括号里的一序列的值,可以为任何数值,也可为空,如(1, 5.3 , "hello" , 2)
,空列表:()
,下面都是列表:
|
|
列表存贮于数组变量中,数组变量以字符”@”打头,以@ages=(25,30,40);
为例说明一下:
数组还可以产使用qw
定义数组,如下所示:
|
|
Perl提供了可以按序列输出的数组形式,格式为起始值 + .. + 结束值
,如下所示:
|
|
数组长度返回的是数组物理大小,而不是元素的个数,如下所示:
|
|
从输出的结果可以看出,数组元素只有四个,但是数组大小为 51。
添加与删除数组元素
添加和删除数组元素,数组中常用的操作函数如下所示:
- push @ARRAY, LIST——将列表的值放到数组的末尾
- pop @ARRAY——弹出数组最后一个值,并返回它
- shift @ARRAY——弹出数组第一个值,并返回它。数组的索引值也依次减一。
- unshift @ARRAY, LIST——将列表放在数组前面,并返回新数组的元素个数。
看下面的案例:
|
|
切割数组
切割一个数组,并返回切割后的新数组,如下所示:
|
|
替换数组元素
Perl 中数组元素替换使用 splice() 函数,语法格式如下:
|
|
参数说明:
- @ARRAY:要替换的数组。
- OFFSET:起始位置。
- LENGTH:替换的元素个数。
- LIST:替换元素列表。
以下案例从第6个元素开始替换数组中的5个元素:
|
|
可以看出来,从第6个元素开始替换,替换的是从第5个元素开始往后的6个元素。
将字符串转换为数组
Perl 中将字符串转换为数组使用 split() 函数,语法格式如下:
|
|
参数说明:
- PATTERN:分隔符,默认为空格。
- EXPR:指定字符串数。
- LIMIT:如果指定该参数,则返回该数组的元素个数。
看下面的案例
|
|
将数组转换为字符串
Perl 中将数组转换为字符串使用 join() 函数,语法格式如下:
|
|
参数说明:
- EXPR:连接符。
- LIST:列表或数组。
如下所示:
|
|
数组排序
Perl 中数组排序使用 sort() 函数,语法格式如下:
|
|
参数说明:
- SUBROUTINE:指定规则。
- LIMIT:列表或数组。
案例如下所示:
|
|
合并数组
数组的元素是以逗号来分割,我们也可以使用逗号来合并数组,如下所示:
|
|
从列表中选择元素
一个列表可以当作一个数组使用,在列表后指定索引值可以读取指定的元素,如下所示:
同样可以在数组中使用 .. 来读取指定范围的元素:
|
|
哈希
哈希是一个key/value
对的集合,可以把它理解为Python中的字典。哈希%
开始。如果要访问哈希值,可以使用$+{key}
格式来访问,如下所示:
|
|
创建哈希
创建哈希有两种方式:第一,为每个key设置value;第二,通过列表创建。
先看第一种方式,如下所示:
第二种,通过列表设置,如下所示:
|
|
也可以使用=>
符号来设置key/value
,如下所示:
|
|
也可以使用-
来代替引号,如下所示:
|
|
不过这种方式创建的哈希,需要key
不能出现空格,读取元素方式为:
|
|
访问哈希
访问哈希元素格式:${key}
,如下所示:
|
|
读取哈希的key
和value
读取hash的key
我们可以使用keys
函数读取哈希所有的键,语法格式如下:
该函数返回所有哈希的所有 key 的数组,如下所示:
|
|
读取hash的value
使用values
函数读取hash的值,如下所示:
|
|
检测元素是否存在
如果你在哈希中读取不存在的key/value
对 ,会返回undefined
值,且在执行时会有警告提醒。为了避免这种情况,我们可以使用exists
函数来判断key
是否存在,存在的时候读取,如下所示:
获取哈希大小
哈希大小为元素的个数,我们可以通过先获取key
或value
的所有元素数组,再计算数组元素多少来获取哈希的大小,如下所示:
哈希中添加或删除元素
delete
函数用于删除哈希中的元素;使用赋值来添加哈希中的元素,如下所示:
|
|
变量上下文
所谓上下文:指的是表达式所在的位置。上下文是由等号左边的变量类型决定的,等号左边是标量,则是标量上下文,等号左边是列表,则是列表上下文。Perl解释器会根据上下文来决定变量的类型,如下所示:
|
|
代码及结果解释:代码中@names
是一个数组,它应用在了两个不同的上下文中。第一个将其复制给另外一个数组@copy
,所以它输出了数组的所有元素。第二个我们将数组赋值给一个标量,它返回了数组的元素个数。以下列出了多种不同的上下文:
序号 | 上下文及描述 |
---|---|
1 | 标量 −赋值给一个标量变量,在标量上下文的右侧计算 |
2 | 列表 −赋值给一个数组或哈希,在列表上下文的右侧计算。 |
3 | 布尔 −布尔上下文是一个简单的表达式计算,查看是否为 true 或 false。 |
4 | Void −这种上下文不需要关系返回什么值,一般不需要返回值。 |
5 | 插值 −这种上下文只发生在引号内。 |
Perl的内置警告信息
从Perl 5.6开始,就能心通过编译指令开启警告功能,如下所示:
|
|
也可以在命令行上使用-w
选项开启警告,如下所示:
|
|
例如,如果用户把12fred34
当成数字用,Perl就会发出警告,如下所示:
|
|
全局特殊常量
在Perl中有一些特殊的字符的应用例如.__FILE__.
, .__LINE__.
和.__PACKAGE__.
(注意,这是一个点加两条下划线),它们分别表示当前执行脚本的文件名,行号,包名,这些特殊字符是单独的标记,不能写在字符串中,如下所示:
|
|
变量 | 描述 |
---|---|
__END__ |
脚本的逻辑结束,忽略后面的文本。 |
__FILE__ |
当前文件名 |
__LINE__ |
当前行号 |
__PACKAGE__ |
当前包名,默认的包名是main。 |
Perl特殊变量
Perl语言中定义了一些特殊的变量,通常以$
,@
,或%
作为前缀,例如$_
。很多特殊的变量有一个很长的英文名,操作系统变量$!
可以写为$OS_ERROR
。如果你想使用英文名的特殊变量需要在程序头部添加use English
;。这样就可以使用具有描述性的英文特殊变量。最常用的特殊变量为$_
,该变量包含了默认输入和模式匹配内容。如下所示:
|
|
如果不使用$_
作为输出,则是这个样子:
|
|
实例中,首先输出”Google”,接着输出”Baidu”,最后输出”Tencent”。在迭代循环中,当前循环的字符串会放在$_
中,然后通过print输出。另外print在不指定输出变量,默认情况下使用的也是$_
。
以下是几处即使没有写明Perl也会假定使用$_
的地方:
- 各种单目函数,包括像
ord()
和int()
这样的函数以及除"-t"
以外所有的文件测试操作("-f","-d")
,"-t"
默认操作STDIN
。 - 各种列表函数,例如
print()
和unlink()
。 - 没有使用
"=~"
运算符时的模式匹配操作"m//"
、"s///"
和"tr///"
。
4 在没有给出其他变量时是"foreach"
循环的默认迭代变量。 grep()
和map()
函数的隐含迭代变量。- 当
"while"
仅有唯一条件,且该条件是对””操作的结果进行测试时,$_
就是存放输入记录的默认位置。除了"while"
测试条件之外不会发生这种情况。(助记:下划线在特定操作中是可以省略的。)
特殊变量类型
根据特殊的变量的使用性质,可以分为以下几类:
- 全局标量特殊变量。
- 全局数组特殊变量。
- 全局哈希特殊变量。
- 全局特殊文件句柄。
- 全局特殊常量。
- 正则表达式特殊变量。
- 文件句柄特殊变量。
全局标量特殊变量
以下列出了所有的标量特殊变量,包含了特殊字符与英文形式的变量:
特殊字符 | 对应的英文形式变量 | 描述 |
---|---|---|
$_ |
$ARG |
默认输入和模式匹配内容。 |
$. |
$NR |
前一次读的文件句柄的当前行号 |
$/ |
$RS |
输入记录分隔符,默认是新行字符。如用undef 这个变量,将读到文件结尾。 |
$, |
$OFS |
输出域分隔符 |
$\ |
$ORS |
输出记录分隔符 |
$" |
$LIST_SEPARATOR |
该变量同 $,类似,但应用于向双引号引起的字符串(或类似的内插字符串)中内插数组和切片值的场合。默认为一个空格。 |
$; |
$SUBSCRIPT_SEPARATOR |
在仿真多维数组时使用的分隔符。默认为 "\034" 。 |
$^L |
$FORMAT_FORMFEED |
发送到输出通道的走纸换页符。默认为 "\f" . |
$: |
$FORMAT_LINE_BREAK_CHARACTERS |
The current set of characters after which a string may be broken to fill continuation fields (starting with ^) in a format. Default is "\n"" . |
$^A |
$ACCUMULATOR |
打印前用于保存格式化数据的变量 |
$# |
$OFMT |
打印数字时默认的数字输出格式(已废弃)。 |
$? |
$CHILD_ERROR |
返回上一个外部命令的状态 |
$! |
$OS_ERROR or $ERRNO |
这个变量的数字值是errno 的值,字符串值是对应的系统错误字符串 |
$@ |
$EVAL_ERROR |
命令eval 的错误消息.如果为空,则表示上一次eval 命令执行成功 |
$$$$ | $PROCESS_ID or $PID |
运行当前Perl脚本程序的进程号 |
$< |
$REAL_USER_ID or $UID |
当前进程的实际用户号 |
$> |
$EFFECTIVE_USER_ID or $EUID |
当前进程的有效用户号 |
$( |
$REAL_GROUP_ID or $GID |
当前进程的实际组用户号 |
$) |
$EFFECTIVE_GROUP_ID or $EGID |
当前进程的有效组用户号 |
0 |
$PROGRAM_NAME |
包含正在执行的脚本的文件名 |
$[ |
数组的数组第一个元素的下标,默认是 0。 | |
$] |
$PERL_VERSION |
Perl的版本号 |
$^D |
$DEBUGGING |
调试标志的值 |
$^E |
$EXTENDED_OS_ERROR |
在非UNIX环境中的操作系统扩展错误信息 |
$^F |
$SYSTEM_FD_MAX |
最大的文件捆述符数值 |
$^H |
由编译器激活的语法检查状态 | |
$^I |
$INPLACE_EDIT |
内置控制编辑器的值 |
$^M |
备用内存池的大小 | |
$^O |
$OSNAME |
操作系统名 |
$^P |
$PERLDB |
指定当前调试值的内部变量 |
$^T |
$BASETIME |
从新世纪开始算起,脚步本以秒计算的开始运行的时间 |
$^W |
$WARNING |
警告开关的当前值 |
$^X |
$EXECUTABLE_NAME |
Perl二进制可执行代码的名字 |
$ARGV |
从默认的文件句柄中读取时的当前文件名 |
全局数组特殊变量
变量 | 描述 |
---|---|
@ARGV |
传给脚本的命令行参数列表 |
@INC |
在导入模块时需要搜索的目录列表 |
@F |
命令行的数组输入 |
全局哈希特殊变量
变量 | 描述 |
---|---|
%INC |
散列表%INC 包含所有用do或require语句包含的文件.关键字是文件名,值是这个文件的路径 |
%ENV |
包含当前环境变量 |
%SIG |
信号列表及其处理方式 |
全局特殊文件句柄
变量 | 描述 |
---|---|
ARGV |
遍历数组变量@ARGV中的所有文件名的特殊文件句柄 |
STDERR |
标准错误输出句柄 |
STDIN |
标准输入句柄 |
STDOUT |
标准输出句柄 |
DATA |
特殊文件句柄引用了在文件中 __END__ 标志后的任何内容包含脚本内容。或者引用一个包含文件中__DATA__ 标志后的所有内容,只要你在同一个包有读取数据,__DATA__ 就存在。 |
_ (下划线) |
特殊的文件句柄用于缓存文件信息(fstat、stat和lstat)。 |
正则表达式特殊变量
变量 | 英文形式变量 | 描述 | |
---|---|---|---|
$n |
包含上次模式匹配的第n个子串 | ||
$& |
$MATCH |
前一次成功模式匹配的字符串 | |
$` |
$PREMATCH |
前次匹配成功的子串之前的内容 | |
$' |
$POSTMATCH |
前次匹配成功的子串之后的内容 | |
$+ |
$LAST_PAREN_MATCH |
与上个正则表达式搜索格式匹配的最后一个括号。例如:`/Version: (.*) | Revision: (.*)/ && ($rev = $+);` |
文件句柄特殊变量
变量 | 英文形式变量 | 描述 | |
---|---|---|---|
`$ | ` | $OUTPUT_AUTOFLUSH |
如果设置为零,在每次调用函数write或print后,自动调用函数fflush,将所写内容写回文件 |
$% |
$FORMAT_PAGE_NUMBER |
当前输出页号 | |
$= |
$FORMAT_LINES_PER_PAGE |
当前每页长度。默认为 60。 | |
$- |
$FORMAT_LINES_LEFT |
当前页剩余的行数 | |
$~ |
$FORMAT_NAME |
当前报表输出格式的名称。默认值是文件句柄名。 | |
$^ |
$FORMAT_TOP_NAME |
当前报表输出表头格式的名称。默认值是带后缀”_TOP”的文件句柄名。 |