Perl正则表达式超详细教程

这篇教程深入讲解Perl正则表达式,包括基本语法、模式匹配修饰符、正则对象创建等内容。教程涵盖i、g、c、m、s等修饰符的用法,以及环视锚定、分组捕获、命名捕获等高级特性,适合有一定正则基础的Perl学习者提升技能。
摘要由CSDN通过智能技术生成

前言

想必学习perl的人,对基础正则表达式都已经熟悉,所以学习perl正则会很轻松。这里我不打算解释基础正则的内容,而是直接介绍基础正则中不具备的但perl支持的功能。关于基础正则表达式的内容,可参阅基础正则表达式

另外,本系列只介绍匹配操作,关于内容替换,因为和学习使用perl正则并无多大关系,所以替换相关的将在下一篇文章单独解释。

这里推荐一个学正则非常好的资料:stackflow上关于各种语言(perl/python/.net/java/ruby等等)的正则的解释、示例,这里收集的都是对问题解释的非常清晰且非常经典的回答。在我学习perl正则的时候,对有些功能实在理解不了(想必你也一定会),就会从这里找答案,而它,也从来没让我失望:https://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean/22944075#22944075

以下是perl正则的man文档:

  • perl正则快速入门:man perlrequick
  • perl正则教程:man perlretut
  • perl正则完整文档:man perlre

学perl正则必备的一点基本语法

新建一个文件作为perl脚本文件,在其首行写上#!/usr/bin/perl,它表示用perl作为本文件的解释器。写入一些perl程序后,再赋予执行权限就可以执行了,或者直接使用perl命令去调用这个脚本文件,前面的两个过程都可以省略,这和shell脚本的方式是完全一样的,无非是将bash替换为了perl,想必各位都理解。

1.print用来输出信息,相当于shell中的echo命令,但需要手动输入换行符"\n"进行换行。

例如:

#!/usr/bin/perl

print "hello world\n";      # 注意每一句后面都使用分号结尾

保存后,执行它(假设脚本文件名为test.pl):

$ chmod +x test.pl
$ perl test.pl

2.变量赋值

perl中的变量可以不用事先声明,可以直接赋值甚至直接引用。注意变量名前面总是需要加上$符号,无论是赋值的时候还是引用的时候,这和其它语言不太一样。

#!/usr/bin/perl

$name="longshuai";
$age=18;
print "$name $age \n";

3.if语句用来判断,语法格式为:

if(condition){
    body
}else{
    body
}

例如:

$age = 18;
if($age <= 20){
    print "age less than 20\n";
} else {
    print "age greate than 20\n";
}

4.默认参数变量

在perl中,对于需要参数的函数或表达式,但却没有给参数,这是将会使用perl的默认参数变量$_

例如,下面的print本来是需要参数的,但是因为没有给参数,print将输出默认的参数变量$_,也就是输出"abcde"。

$_="abcde";
print ;

perl中使用$_的地方非常多,后文还会出现,不过用到的时候我会解释。

5.读取标准输入

perl中使用一对尖括号格式的<STDIN>来读取来自非文件的标准输入,例如来自管道的数据,来自输入重定向的数据或者来自键盘的输入。需要注意的是,<STDIN>读取的输入会自带换行符,所以print输出的时候不要加上额外的换行符。

例如,在test.pl文件中写入如下内容:

#!/usr/bin/perl

$data=<STDIN>;
print "$data";

然后用管道传递一行数据给perl程序:

echo "abcdefg" | perl test.pl

只是需要注意,将<STDIN>赋值给变量时,将只能读取一行(遇到换行符就结束读取)。例如下面的perl将读取不了"hijklmn"。

echo -e "abcdefg\nhijklmn" | perl test.pl

如果想要读取多行标准输入,就不能将其赋值给变量,而是使用foreach来遍历各行(此处不介绍其它方式):

foreach $line (<STDIN>){
    print "$line";
}

以上就是foreach的语法:

  • 圆括号中的内容是待遍历对象,通常是一个列表,比如上面用<STDIN>读取的多行数据就是一个列表,每一行都是列表中的一个元素;
  • $line称为控制变量,foreach在每次迭代过程中都会选中一个列表中的元素赋值给$line,例如将读取的每一行都赋值给$line。

可以省略$line,这时就采用默认的参数变量$_,所以以下两个表达式是等价的:

foreach (<STDIN>){
    print "$_";
}

foreach $_ (<STDIN>){
    print "$_";
}

6.读取文件中的数据

正则强大的用处就是处理文本数据,所以必须要说明perl如何读取文件数据来做正则匹配。

我们可以将文件作为perl命令行的参数,perl会使用<>去读取这些文件中的内容。

foreach (<>){
    print "$_";
}

执行的时候,只要把文件作为perl命令或脚本文件的参数即可:

perl test.pl /etc/passwd

7.去掉行尾分隔符

由于<><STDIN>读取文件、读取标准输入的时候总是自带换行符,很多时候这个自带的换行符都会带来格式问题。所以,有必要在每次读取数据时将行尾的换行符去掉,使用chomp即可。

例如:

foreach $line (<STDIN>) {
    chomp $line;
    print "$line read\n";
}

以下是执行结果:

[root@xuexi ~]# echo -e "malongshuai gaoxiaofang" | perl 26.plx 
malongshuai gaoxiaofang read

如果上面的例子中不加上chomp,那么执行结果将像下面一样:

[root@xuexi perlapp]# echo -e "malongshuai gaoxiaofang" | perl 26.plx 
malongshuai gaoxiaofang
 read

显然,输出格式和print语句中期待的输出格式不一样。

前面说过,可以省略$line,让其使用默认的参数变量$_,所以可以这样读取来自perl命令行参数文件的数据:

foreach (<>) {
    chomp;
    print "$_ read\n";
}

8.命令行的操作模式

其实就是一行式。perl命令行加上"-e"选项,就能在perl命令行中直接写perl表达式,例如:

echo "malongshuai" | perl -e '$name=<STDIN>;print $name;'

因为perl最为人所知的就是它应用了各种符号的组合,让人看着怪异无比,而这些符号放在命令行中很可能会被shell先解析,所以强烈建议"-e"后表达式使用单引号包围,而不是双引号。

更建议,如果可以,不要使用perl命令行的方式,调试起来容易混乱。

perl如何使用正则进行匹配

使用=~符号表示要用右边的正则表达式对左边的数据进行匹配。正则表达式的书写方式为m//。关于m//,其中斜线可以替换为其它符号,规则如下:

  • 双斜线可以替换为任意其它对应符号,例如对称的括号类,m()m{},相同的标点类,m!!m%%等等
  • 只有当m模式采用双斜线的时候,可以省略m字母,即//等价于m//
  • 如果正则表达式中出现了和分隔符相同的字符,可以转义表达式中的符号,但更建议换分隔符,例如/http:\/\//转换成m%http://%

所以要匹配内容,有以下两种方式:

  • 方式一:使用data =~ m/reg/,可以明确指定要对data对应的内容进行正则匹配
  • 方式二:直接/reg/,因为省略了参数,所以使用默认参数变量,它等价于$_ =~ m/reg/,也就是对$_保存的内容进行正则匹配

perl中匹配操作返回的是匹配成功与否,成功则返回真,匹配不成功则返回假。当然,perl提供了特殊变量允许访问匹配到的内容,甚至匹配内容之前的数据、匹配内容之后的数据都提供了相关变量以便访问。见下面的示例。

例如:

1.匹配给定字符串内容

$name = "hello gaoxiaofang";
if ($name =~ m/gao/){
    print "matched\n";
}

或者,直接将字符串拿来匹配:

"hello gaoxiaofang" =~ m/gao/;

2.匹配来自管道的每一行内容,匹配成功的行则输出

foreach (<STDIN>){
    chomp;
    if (/gao/){
        print "$_ was matched 'gao'\n";
    }
}

上面使用了默认的参数变量$_,它表示foreach迭代的每一行数据;上面还简写的正则匹配方式/gao/,它等价于$_ =~ m/gao/

以下是执行结果:

[root@xuexi perlapp]# echo -e "malongshuai gaoxiaofang" | perl 26.plx  
malongshuai gaoxiaofang was matched 'gao'

3.匹配文件中每行数据

foreach (<>){
    chomp;
    if(/gao/){
        print "$_ was matched 'gao'\n";
    }
}

4.如果想要输出匹配到的内容,可以使用特殊变量$&来引用匹配到的内容,还可以使用$`引用匹配前面部分的内容,$'引用匹配后面部分的内容

例如:

aAbBcC =~ /bB/

由于匹配的内容是bB,匹配内容之前的部分是aA,匹配之后的部分是cC,于是可以看作下面对应关系:

 (aA)(bB)(cC)
 |    |   |
 $`   $&  $'

以下是使用这三个特殊变量的示例:

$name="aAbBcC";
if(/bB/){
    print "pre match: $` \n";
    print "match: $& \n";
    print "post match: $' \n";
}

需要注意的是,正则中一般都提供全局匹配的功能,perl中使用修饰符/g开启。当开启了全局匹配功能,这3个变量保存的值需要使用循环语句去遍历,否则将只保存第一次匹配的内容。例如:

$name="aAbBcCbB";
if(/bB/g){  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值