[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
选择Unix中有两种版本:
- 源代码 : https://www.cpan.org/src/5.0/perl-5.30.0.tar.gz
- 二进制包 : https://www.activestate.com/activeperl/downloads
Unix 和 Linux 安装 Perl:安装成功后Perl 的安装路径为/usr/local/bin,库安装在 /usr/local/lib/perlXX, XX 为版本号。
代码语言:javascript复制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
接下来我们如果 perl -v 命令查看是否安装成功。
代码语言:javascript复制perl -v
This is perl 5, version 30, subversion 0 (v5.30.0) built for x86_64-linux
Perl语法基础
CMD语法:
代码语言:javascript复制perl5.26.2 [switches] [--] [programfile] [arguments]
Perl参数:
代码语言:javascript复制-e/E "Perl代码" #直接执行代码
-l
-p #表示对目标文件的每一行进行查找和替换
-i #表示将替换的结果写回到文件之中
-w/W #warning 在程序执行可疑的地方发出警报
变量的声明使用与php相似都是采用$变量名称进行定义变量和调用变量;
代码语言:javascript复制#基础示例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(哈希)
注意事项:
- Perl通常情况是不区分整数和浮点数;
Perl运算操作符:
- 赋值
- 判断
- 逻辑 (and / or / not)
- 位
- 其他操作符号
- <> 每次读取一行数据相当于其他语言中的getline()函数.注意不要混淆操作符<>与shell的重定向符号>或者是Perl的大小于号;
#读取每一行数据
while($line = <>) {
#处理$line
}
基础示例1:
代码语言:javascript复制#!/usr/bin/perl
# Function:计算华氏温度和摄氏温度
$celsius = 30;
$fahrenheit = ($celsius * 9 / 5) 32;
print "$fahrenheit F, And $celsius ℃n";
执行结果:
代码语言:javascript复制perl demo1.pl
86 F, And 30 ℃
注意事项:
- (1)Perl符号=~ / = 和 == 之间的差别,等于 ==测试两个数字是否相等, = 用来给变量赋值,
而=~用来连接正则表达式m/.../和待搜索的目标字符串
。
Perl控制结构
代码语言:javascript复制#条件结构
if(条件){
...
}else if(条件){
...
}else{
...
}
#循环结构
while()
{
last; #停止while循环内的处理跳出循环
}
Perl也提供与其他流行语言类似的控制结构:
基础示例2:
代码语言:javascript复制#!/usr/bin/perl
#FUNCTION: 实现判断语句与while循环
$num1 = 1024;
$num2 = 1;
$sum = 0;
if( $num1 != "" && $num2 != "" )
{
$add = $num1 $num2;
print "$num1 $num2 = $addn";
}
while($num <= 100)
{
$sum = $sum $num;
$num ;
}
print "1 .. 3 ... 7 100 = $sum n";
执行结果:
代码语言:javascript复制perl demo2.pl
1024 1 = 1025
1 .. 3 ... 7 100 = 5050
Perl正则表达式
描述:perl和Egrep属于同一个流派,Perl支持Regex的一些修饰符的使用并且Perl正则表达式中的元字符更多;
代码语言:javascript复制$variable=~ m/regularExpression/i #来判断一个正则表示是是否能匹配某个字符串;
#整个测试语句作为一个单元返回boolean类型返回TRUE或者FALSE;
m #表示进行整治match匹配;
s #表示进行替换replace操作
/ #斜线表示正则表达式的边界;
/i #该修饰符modifier表示不区分大小写匹配
/g #该修饰符表示全局匹配(global Macth)
/x #表示宽松排列的表达式(free-from expressions)允许我们重新编排这个表达式(大多空白字符会被忽略),增强可读性;
/m #增强的行瞄点(enhanced line anchor),^$将切换到逻辑行模式;
- Perl提供例如许多简洁的元字符:
- cx 匹配由X指明的控制字符
- n : 换行符
- f : ASCII 进制符号
- t : tab键符号
- b : 退格键
- v : 垂直制表符
$ perl -E 'if("anbtc" =~ m/cI|n/){print "匹配成功"}'
匹配成功
$ perl -E 'if("anbc" =~ m/cI|n/){print "匹配成功"}'
匹配成功
Perl支持捕获括号()
我们叫元组与非捕获类型括号(?:...)
表示只分组不补捕获;
() #元组匹配成功之后Perl可以用$1 $2 $3 之类的变量来保存相对应的()括号内的子表达式匹配的文本;
(?:....)
注意事项:
- 在元组中子表达式的编号安装开括号的出现先后排序,从1开始子表达式可以嵌套例如(Washington(.DC)?)
- 如果只是希望分组,也可以使用()但副作用是他们捕获的文本任然会保存在特殊的变量之中;
3.Perl正则中的环视功能
代码语言:javascript复制(?=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:
代码语言:javascript复制#!/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 digitsn"
} else {
print "not only digitsn"
}
#方式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 Fn", $cel, $fah;
} else {
print "Matching Error!"
}
执行结果:
代码语言:javascript复制[root@master perl]# perl demo3.pl
Please Enter a number(Eg:1024):1024bac
not only digits
[root@master perl]$perl -w demo4.pl
Please input 86 F or 30 C : 30C
30 C And 86.00 F
[root@master perl]$perlperl -w demo4.pl
Please input 86 F or 30 C : 86F
30 C And 86.00 F
[root@master 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))
代码语言:javascript复制#!/bin/perl
#替换修改文本
#示例1
$string = "this is a demo";
$string =~ s/is/test/gi; #或者直接在源字符上操作(全局替换)
print "$string";
$string = "this is a demo";
$string =~ s/bisb/test/i; #或者直接在源字符上操作(只替换一次)
print "$string";
##示例2.保留小数点后的两位
$iee = 12.375000392;
$iee =~ s/(d )(.dd[1-9]?)d*/$1$2/;
print "$iee ";
$iee = 37.500000000925;
$iee =~ s/(d )(.dd[1-9]?)d*/$1$2/;
print "$iee ";
执行结果:
代码语言:javascript复制$ perl replace.pl
thtest test a demo
this test a demo
12.375
37.5
基础示例3:
代码语言:javascript复制#示例1.再perl的cmd中需要对一些字符进行八进制代替比如 ' = 47 ,替换的时候也可以采用 nm模式
perl -l -e '$str="Window 47s 98";if($str =~ s/47/ 57/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内置函数
代码语言:javascript复制defined($var); #验证变量是否定义
die "Error Exit!"; #类似于php中的die()函数发出错误信息
入坑解决
问题1.在编译perl源代码时候发生错误
代码语言:javascript复制perl: warning: Falling back to a fallback locale ("en_US.UTF-8")
#解决方法:
vim ~/.bashrc
export LC_ALL=en_US.UTF-8
. ~/.bashrc #然后加载该环境变量