[TOC]
scalar和array的记法
| 
 | 
 | 
还是挺巧妙的, 不过%hash就没什么的了.
字符串tricks
犀利的qw
qw表示quoted words:
| 
 | 
 | 
此外, 用了qw就不限于用括号序对了, 可以用的序对符有:
| 
 | 
 | 
好灵活的。
a..b递增数字序列
生成(a, a+1, a+2,..., b-1, b),这里当然b是要大于a的. 测试了一下, a大于b的话返回的是一个空列表.
字符串插值
"@array"与'@array'是不同的, 前者会进行列表值的插入展开, 而后者则是原始的literal字符串不进行展开.
插值的形式不止于此, 比如"\Lstr"会将str全都变成小写, 相应的"\Ustr"会将字符串全都变成大写字母.
字符串duplicate
| 
 | 
 | 
相当于python里的str*n, PERL在这方面果然不会落后.
格式化字符串
用的是%:
- %g, 指定自动数字形式;
- %-n, 指定宽度为n个字符, 左对齐;
- %n, 指定宽度为n个字符, 右对齐;
- %%, 输出百分号%
可变宽度的字符串可以用:
| 
 | 
 | 
sprintf函数也接收格式化字符串, 不过不打印出来, 而是用于保存到变量里.
这样的两种形式.
$#<list_name>列表长度(-1)
返回的是list的个数-1,因此可以使用$list_name[$#list_name]来获取列表的最后一个值.
build-in函数杂计
splice
原型是:
| 
 | 
 | 
arg1为目标列表, arg2为起始位置(从1开始计), arg3为作用的长度, arg4为替换进去的列表.
示例中@remove为切出的列表, arg1为作用后的结果列表, 与直觉不相符呢.
而且要注意的是在列表遍历中(典型的如foreach)中对遍历成员的操作会影响目标列表, 这个或许是splice的这种行为的原因.
unlink和glob
unlink和glob相当于shell中的rm和glob, 即unlink glob '*.o'就相当于在shell中执行rm *.o, 不过推荐的执行方式如下:
| 
 | 
 | 
index和rindex
直接看例子:
| 
 | 
 | 
$location_int为@heap中首次出现$needle的位置.
还有个rindex是反向查找.
grep
grep跟shell里的grep没有关系, 其实跟FP里的filter是一个意思, 直接看代码示例吧:
| 
 | 
 | 
最后一条加了一个context变换的trick而已.
特殊变量
$_默认变量
直接上代码好了:
| 
 | 
 | 
$_在这里起到了一个表达式”管道”的作用.
函数中的@_
@_是函数的私有变量, 表示函数的参数列表, 可以用$_[n]来进行逐个索引访问.
@_跟默认变量$_是没有任何关系的.
命令行参数@ARGV与钻石操作符<>
命令行的参数保存在@ARGV里. 
<>将@ARGV中指定全部文件打开并将文件句柄全都存储在<>内, 当然@ARGV也可以显式的认为修改. 如果@ARGV中没有参数, 则<>使用<STDIN>.
| 
 | 
 | 
$!
$!中存放着系统错误信息.
上面的代码等价于一个cat命令, 当然这个命令可以写的更简单一点: print <>.
$1, $2, ... $n
为正则表达式匹配之后的分组内容捕获, 各个变量表示分组匹配的内容.
正则表达式默认匹配变量
$(apostrophe)$&$'为正则表达式匹配之后的默认变量, $`表示匹配内容之前的字符串, $&表示匹配的字符串, $'表示匹配内容之后的字符串.
$^I备份文件变量
用$^I = "*.bak"这样的形式来设置备份文件.
$a和$b
排序子程序中的默认变量, 表示要进行比较的两个输入.
上下文context
@array在列表上下文中返回列表的列表项目值, 在标量上下文中返回列表元素的个数, scalar @array会强制制造标量上下文, 返回@array的列表元素个数.
<STDIN>标准输入
<STDIN>其实是一个句柄啦, 指向标准输入, 也就是键盘, 标准用法是这样的:
chomp(@lines = <STDIN>);
表示读取C-D之前的所有键盘输入内容, 每行去掉换行符然后存到列表@lines里面.
函数
定义与调用
定义格式为:
| 
 | 
 | 
调用的格式为:
| 
 | 
 | 
在调用时, 如果没有跟build-in函数名冲突, 可以不用加&符号(build-in函数是不用加符号的). 其实这种设置灵活是零活, 但是还是都加&的好.
另外, 函数结束前执行的最后一步的结果会作为返回值, 除非显式的使用return. 这个的话依然还是统一用return比较好.
my创建变量
使用my可以创建作用域内的变量, 典型的就是函数内部啦:
| 
 | 
 | 
此外, 还可以用于if, while, foreach的作用域内, 比如:
| 
 | 
 | 
state
用state创建的是函数的静态变量.
for和foreach
foreach是for的一个子集, for(@args)和foreach(@args)是可以互相替换的, 此外for的另外的用法就是常见的for($i = 0; $i < n; $i++).
文件句柄
| 
 | 
 | 
要注意使用的文件符为单引号, 读写指定符跟命令行的管道重定向符号是一致的. 往文件里面添加内容直接使用第6行的格式即可.
select可以选择默认句柄, 用来取代STDIN和STDOUT.
hash
%var表示一个哈希变量.
hash的reverse
my %inverse_hash = reverse %any_hash;
使原来的k-v对转换为v-k对, 根据hash的默认属性, 这样翻转需要原先的v中没有重复值, 不然就会出现转换后k值的覆盖.
keys, values函数
分别返回哈希表的键列表和值列表:
| 
 | 
 | 
另外each可以直接返回键值对:
| 
 | 
 | 
正则表达式
属性元字符
形式为: \p{property}, 比较重要的几个列举如下:
- \p{Space}: 表示Unicode中定义的空格;
- \p{Digit}: 表示Unicode中定义的数字;
- \p{Hex}: 表示16进制字符, 相当于- [0-9A-Fa-f];
- \P{property}: 表示反义;
具体的内容查阅perluniprops吧.
括号分组
正则表达式中的组号以左括号从左至右的顺序从1开始编号, \1, \2, ... \n为正则表达式中的引用, $1, $2, ...$n为正则表达式匹配之后的组内容捕获.
另外可以使用\g{n}这样的形式, 以消除\111这样的歧义(\111表示第111组, 还是第1组后面跟11还是表示11组后面跟1呢?).
更研究的方法是用label来命名分组—(?<label_name>pattern), 然后用\g{label_name}引用, 用${label_name}来获取捕获内容.
(?:pattern)表示不占用组号的分组.
默认匹配变量
$(apostrophe)$&$'为正则表达式匹配之后的默认变量, $`表示匹配内容之前的字符串, $&表示匹配的字符串, $'表示匹配内容之后的字符串, 一个可以用来做正则匹配调试的程序如下:
| 
 | 
 | 
匹配选项
写在正则表达式的最后面—/pattern/option_mark, 常用的选项有:
- /g: 获取所有的匹配, 即返回到一个array而不是scalar里;
- /i: 忽略大小写;
- /s: 使- .匹配- \n;
- /x: 忽略正则表达式中的空格, 使用这个选项可以写出可能性明显提升的正则表达式, 因为使用了这个选项就可以对正则表达式进行断行了, 并且可以在每行都写上注释.
单行流例程
| 
 | 
 | 
-p相当于是:
| 
 | 
 | 
意思是打印每一行, -e指定的内容就填充到print这一句之上.
-w相当于是代码中的第一行, 打开warning开关的意思, -i.bak就相当于是$^I = ".bak"设置同名备份文件的意思了.
模块使用
| 
 | 
 | 
表示引入模块中的...函数, 为空的话表示不引入.
Try::Tiny
用了这个模块就可以用try catch了. 不过这个模块需要从CPAN中下载.
List::Util
标准库中的列表处理库, 里面有shuffle(@list)这种函数, 应该很实用.
排序子程序
| 
 | 
 | 
上面的这个就是一个排序程序, $a和$b表示顺序赋值的两个输入. 上面的程序用于sort的排序子程序中, 相当于sort的一个callback.
上面的程序表示按数值从大往小排序, 应用方式为:
my @result = sort by_name @some_num;
可以替换为:
my @result = sort {$a <=> $b} @some_num;
上面的那个排序程序也可以简化为:
sub by_name {$a <=> $b};
按字符排序的子程序写法是:
sub by_code_point {$a cmp $b}
这个就是sort的默认行为.
进行反向排序的话就交换一下两个排序变量的顺序就可以了.
ps: 排序子函数的函数名用by_前缀的形式似乎是个convention.
哈希表多重排序应用
| 
 | 
 | 
上面的排序程序表示先按分数从小到大排序, 同分的话再按字母排序.
数组切片和哈希切片
直接上代码说明, 数组切片:
| 
 | 
 | 
哈希切片:
| 
 | 
 | 
要注意哈希的上下文.