[TOC]

快速入门

Perl 是 Practical Extraction and Report Language 的缩写”实用报表提取语言”是一种功能强大功能丰富的脚本编程语言,最初的设计者为拉里·沃尔(Larry Wall)诞生于20世纪80年代末期并由他不断更新和维护的编程语言。

其思想借用了C、sed、awk、shell脚本以及很多其他编程语言的特性,所以它的文本处理能力是及其强大的是关于Web处理中最常用使用的工具;

优点和特点:

  • Perl是高级、通用、直译式、动态、灵活的程序脚本语言(不需要编译器和链接器来运行代码)
  • Perl跨平台性 Dos/windows,MacOS,OS/2,VM2和Unix
  • Perl语言直接提供泛型变量、动态数组、Hash表等更加便捷的编程元素,提供了许多冗余语法。
  • Perl最重要的特性是Perl内部集成了正则表达式的功能,以及巨大的第三方代码库CPAN可扩展性强
  • Perl提供了许多其他紧凑的数据处理结果(data-handling contructs),能够减少所需的”简单重复的劳动”,把更多的精力放在程序设计和正则表达式上;
  • Perl的mod_perl 的模块允许 Apache web 服务器使用 Perl 解释器。

_缺点_:

  • Perl程序可以写得很随意因为Perl的灵活性和”过度”的冗余语法,也因此获得了仅写(write-only)的”美誉”
  • Perl程序的代码令人难以阅读,实现相同功能的程序代码长度可以相差十倍百倍
  • perl进程某一时刻会占用很多的内存空间

    建议的解决方法是在程序里使用use strict;以及use warnings;,并统一代码风格,使用库,而不是自己使用”硬编码”。Perl同样可以将代码书写得像Python或Ruby等语言一样优雅。


perl安装

描述:Perl的官网网站:http://www.perl.org/ ,目前Perl版本5.30.0;

WeiyiGeek.Perl

WeiyiGeek.Perl

选择Unix中有两种版本:

Unix 和 Linux 安装 Perl:安装成功后Perl 的安装路径为/usr/local/bin,库安装在 /usr/local/lib/perlXX, XX 为版本号。

1
2
3
4
wget https://www.cpan.org/src/5.0/perl-5.30.0.tar.gz
tar -xzf perl-5.30.0.tar.gz
./Configure -de
make && make test && make install

WeiyiGeek.PerlInstall

WeiyiGeek.PerlInstall

接下来我们如果 perl -v 命令查看是否安装成功。

1
2
perl -v
This is perl 5, version 30, subversion 0 (v5.30.0) built for x86_64-linux


Perl语法基础

CMD语法:

1
perl5.26.2 [switches] [--] [programfile] [arguments]

Perl参数:

1
2
3
4
5
-e/E "Perl代码"  #直接执行代码
-l
-p #表示对目标文件的每一行进行查找和替换
-i #表示将替换的结果写回到文件之中
-w/W #warning 在程序执行可疑的地方发出警报

变量的声明使用与php相似都是采用$变量名称进行定义变量和调用变量;

1
2
3
4
5
6
7
8
9
#基础示例1
perl -e "print 'This is a Demo'"
This is a Demo

#示例2.命令行替换文件中的文本
perl -p -i -e 's/sysread/read/g' file.txt

#示例2.额外的功能
perl -w script.pl string.txt #string是要被提取的源文本

特殊变量

  • $/ 特殊变量能使用一种神奇的方式,让<>不再返回单行文字,而是返回或多或少的一段文件。返回的数据任然是一个字符串,只是这个字符串可能包含多个逻辑行;
Perl数据类型:
  • 数值
  • 字符串
  • 数组
  • Hash(哈希)
1
2


注意事项:

  • Perl通常情况是不区分整数和浮点数;


Perl运算操作符:
  • 赋值
  • 判断
  • 逻辑 (and / or / not)
  • 其他操作符号
    • <> 每次读取一行数据相当于其他语言中的getline()函数.注意不要混淆操作符<>与shell的重定向符号>或者是Perl的大小于号;
1
2
3
4
5

#读取每一行数据
while($line = <>) {
#处理$line
}

基础示例1:

1
2
3
4
5
#!/usr/bin/perl
# Function:计算华氏温度和摄氏温度
$celsius = 30;
$fahrenheit = ($celsius * 9 / 5) + 32;
print "$fahrenheit F, And $celsius ℃\n";

执行结果:
1
2
perl demo1.pl
86 F, And 30 ℃

注意事项:

  • (1)Perl符号=~ / = 和 \=\= 之间的差别,等于 \=\=测试两个数字是否相等, = 用来给变量赋值,而=~用来连接正则表达式m/.../和待搜索的目标字符串
Perl控制结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#条件结构
if(条件){
...
}else if(条件){
...
}else{
...
}

#循环结构
while()
{
last; #停止while循环内的处理跳出循环
}

Perl也提供与其他流行语言类似的控制结构:

基础示例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/perl
#FUNCTION: 实现判断语句与while循环
$num1 = 1024;
$num2 = 1;
$sum = 0;

if( $num1 != "" && $num2 != "" )
{
$add = $num1 + $num2;
print "$num1 + $num2 = $add\n";
}

while($num <= 100)
{
$sum = $sum + $num;
$num++;
}

print "1+..+3+...+7+100 = $sum \n";

执行结果:
1
2
3
perl demo2.pl
1024 + 1 = 1025
1+..+3+...+7+100 = 5050


Perl正则表达式

描述:perl和Egrep属于同一个流派,Perl支持Regex的一些修饰符的使用并且Perl正则表达式中的元字符更多;

1
2
3
4
5
6
7
8
9
$variable=~ m/regularExpression/i #来判断一个正则表示是是否能匹配某个字符串;
#整个测试语句作为一个单元返回boolean类型返回TRUE或者FALSE;
m #表示进行整治match匹配;
s #表示进行替换replace操作
/ #斜线表示正则表达式的边界;
/i #该修饰符modifier表示不区分大小写匹配
/g #该修饰符表示全局匹配(global Macth)
/x #表示宽松排列的表达式(free-from expressions)允许我们重新编排这个表达式(大多空白字符会被忽略),增强可读性;
/m #增强的行瞄点(enhanced line anchor),^$将切换到逻辑行模式;

  1. Perl提供例如许多简洁的元字符:
  • \cx 匹配由X指明的控制字符
  • \n : 换行符
  • \f : ASCII 进制符号
  • \t : tab键符号
  • \b : 退格键
  • \v : 垂直制表符
1
2
3
4
$ perl -E 'if("a\nb\tc" =~ m/\cI|\n/){print "匹配成功"}'
匹配成功
$ perl -E 'if("a\nbc" =~ m/\cI|\n/){print "匹配成功"}'
匹配成功


  1. Perl支持捕获括号()我们叫元组与非捕获类型括号(?:...)表示只分组不补捕获;
    1
    2
    () #元组匹配成功之后Perl可以用$1 $2 $3 之类的变量来保存相对应的()括号内的子表达式匹配的文本;
    (?:....)

注意事项:

  • 在元组中子表达式的编号安装开括号的出现先后排序,从1开始子表达式可以嵌套例如(Washington(.DC)?)
  • 如果只是希望分组,也可以使用()但副作用是他们捕获的文本任然会保存在特殊的变量之中;

3.Perl正则中的环视功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(?=pattern) #肯定型顺序环视(positive lookahread)(从左向右)  正向预查(能匹配pattern)
#例如(?=\d)表示如果当前位置 右边字符 是数字则匹配成功;
#例如'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。

(?!=pattern) #否定型顺序环视(negativ lookahread)(从左向右) 负向预查(不能匹配pattern)
#例如(?!=\d)表示如果当前位置 右边字符 不能是数字则匹配成功;
#例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的

(?<=pattern) #肯定型逆序环视(从右向左)查看文本 反向肯定预查与正向肯定预查类似,只是方向相反。注意空格
#例如(?<=\d)表示如果当前位置 左边字符 是数字则匹配成功;(?<=19)99 则匹配1999后面的99
#例如Windows( ?<=95|98|NT|2000|10)能匹配“98/NT/2000/10/Windows”中的“Windows”,但不能匹配“95Windows”中的“Windows”,软件不一定全部支持
perl -l -e '$str="Windows2000 95Windows 2000Windows Windows95";if($str =~ s/Windows( ?<=95|98|NT|2000|10)/NOW/g){print "匹配成功 $str"}'
# 匹配成功 NOW 95Windows 2000Windows Windows95

(?<!pattern) #肯定型逆序环视(从右向左)查看文本;
#例如(?<!\d)表示如果当前位置 左边字符 不能是数字则匹配成功;(?<!19)99 则匹配非1999后面的99,比如这时匹配2099中的99
#例如Windows( ?<!95|98|NT|2000|10)能匹配“95Windows”中的“Windows” 不能匹配“98/NT/2000/10/Windows”中的“Windows”


Perl多种方式使用正则表达式:
基础示例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/perl
#function:验证Perl正则表达式进行匹配
#方式1:接受用户输入并且判断校验输入
print "Please Enter a number(Eg:1024):";
$demo = <STDIN>; #交互式接收用户输入
chomp($demo); #去掉$demo变量中输入的换行符
# 关键点:注意=~符号后的 m/,匹配成功返回true否则false
if ($demo =~ m/^[0-9]+$/) {
print "only digits\n"
} else {
print "not only digits\n"
}


#方式2:精确匹配整数负数以及小数
$demo =~ m/^[-+]?[0-9]+(\.[0-9]*)?$/) #^配置行首 $匹配结尾


#方式3:或者输入摄氏温度或者华氏温度进行转换
printf "Please input 86 F or 30 C:";
$value = <STDIN>;
chomp($value);

#第一个括号: 整个正则表达式保存位$1
#第二个括号: 保存是输入的华氏温度还是摄氏温度保存位$2
if($value =~ m/^([-+]?[0-9]+)([CF])$/)
{
#重点
$number = $1; #将输入温度数据保存到变量中
$type = $2; #将输入变量的类型保存到变量

#判断字符串是否相等
if($type eq "C"){
$cel = $number;
$fah = ($cel * 9 / 5) + 32;
} else {
$fah = $number;
$cel = ($fah - 32) * 5 / 9;
}
#计算输入两个温度值采用printf函数(与C中函数类似)
printf "%2.f C And %.2f F\n", $cel, $fah;
} else {
print "Matching Error!"
}

执行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[[email protected] perl]# perl demo3.pl
Please Enter a number(Eg:1024):1024bac
not only digits

[[email protected] perl]$perl -w demo4.pl
Please input 86 F or 30 C : 30C
30 C And 86.00 F

[[email protected] perl]$perlperl -w demo4.pl
Please input 86 F or 30 C : 86F
30 C And 86.00 F

[[email protected] perl]$perl -w demo4.pl
Please input 86 F or 30 C : 76F
24 C And 76.00 F


基础示例2:使用正则表达式修改文本
描述:Perl和其他许多语言提供的一个正则表达式特性:替换(substiution或者叫做查找和替换(search and replace))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/perl
#替换修改文本
#示例1
$string = "this is a demo";
$string =~ s/is/test/gi; #或者直接在源字符上操作(全局替换)
print "$string";

$string = "this is a demo";
$string =~ s/\bis\b/test/i; #或者直接在源字符上操作(只替换一次)
print "$string";

##示例2.保留小数点后的两位
$iee = 12.375000392;
$iee =~ s/(\d+)(\.\d\d[1-9]?)\d*/$1$2/;
print "$iee ";

$iee = 37.500000000925;
$iee =~ s/(\d+)(\.\d\d[1-9]?)\d*/$1$2/;
print "$iee ";

执行结果:
1
2
3
4
5
6
$ perl replace.pl
thtest test a demo
this test a demo

12.375
37.5



基础示例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#示例1.再perl的cmd中需要对一些字符进行八进制代替比如 ' = \047 ,替换的时候也可以采用\0nm模式
perl -l -e '$str="Window\047s 98";if($str =~ s/\47/\057/g){print "匹配成功 $str"}'
匹配成功 Window/s 98

#示例2./x修饰符重新编排表达式
$text =~ s {
\b
(
username
\@
hostname
)
\b
}{<a href="mailto:$1">$1</a>}gix

补充说明:
为什么有时候Perl在使用正则匹配的需要对$和@需要转义

  • $符号既可以作为字符串结束字符,又可以在Perl中作为标记变量;
  • @情况与之类似,Perl用@表示数组名,在Perl中的字符串或者正则表达式中也可以容许出现数组变量;如果需要使用@字符就需要进行转义避免把他作为数组名称;

perl内置函数

1
2
defined($var);  #验证变量是否定义
die "Error Exit!"; #类似于php中的die()函数发出错误信息

入坑解决

问题1.在编译perl源代码时候发生错误

1
2
3
4
5
6
perl: warning: Falling back to a fallback locale ("en_US.UTF-8")

#解决方法:
vim ~/.bashrc
export LC_ALL=en_US.UTF-8
. ~/.bashrc #然后加载该环境变量