Perl学习笔记-2(正则表达式)

Perl的正则表达式支持

  1. 使用简单模式
    若模式匹配的对象是$_的内容,只需把模式写在一对斜线(/)中就可以了。
$_="yabde sdfe doo";
if(/sdfe/){
	print "matched!\n"
}

在简单模式匹配中如何使用不匹配的模式(反模式)

# 输出不包含"/bin/bash"的行
......
if(/^((?!\/bin\/bash).)*$/){
	......
}
......

# 命令行方式
getent passwd | perl -ne 'print if /^((?!\/bin\/bash).)*$/'

这里使用到的反模式是

# 不包含string的行
/^((?!string).)*$/
  1. Unicode属性匹配
if(/\p{Space}/){ #带有空白字符的属性
	...
}
if(/\p{Digit}/){ #数字字符
	...
}
if(/\p{Hex}\p{Hex}/){ #匹配2位十六进制数
	...
}
if(/\P{Space}/){ #非空白字符
	...
}
  1. 反向引用
$_="abba";
if(/(.)\1/){
	...
}

消除反向引用的奇异

$_="aa11bb";
if(/(.)\g{1}11/){ #绝对分组编号
	...
}
相对分组编号
$_="xaa11bb";
if(/(.)(.)\g{-1}11/){ #本尊的前一个引用
	...
}

按老的ASCII字符集来解释

if(/\s/a){
	...
}
  1. 通用断行符
\R会匹配:
\r\n
\n
  1. 正则表达式匹配
    匹配方式” m// “,其中的” / “可以使用其他字符,如##,!!,^^,(),{},<>,[]等。
    当使用/时,可以省略m。

  2. 模式匹配修饰符

修饰符含义
/a使用ASCII字符集
/u使用unicode字符集
/i大小写无关匹配
/s. 无法匹配换行符。这适用于单行匹配。用于匹配字符串中的回车换行符。
/x模式字符串中可以有额外的空白符。还可以忽略#注释。

上述修饰符可以组合使用,且不用操心先后顺序。

注意:
\N表示非\n。
7. 锚位

绝对开头
m{\Ahttps?://}i
绝对末尾
m{\.png\z}
\Z允许后边出现换行符。

while(<STDIN>){
	print if /\.png\Z/;
}

while(<STDIN>){
	chomp;
	print "$_\n" if /\.png\z/;
}

匹配含空白的行
/\A\s*\Z/
  1. 绑定操作符=~
    默认匹配$_,通过=~来绑定匹配模式。
if($some_other =~ /\brub/){
	...
}
  1. 模式中的内插
if(/\A($what)/){
	...
}

10.捕获变量
在匹配操作结束后通过捕获变量取得捕获组的内容。
$1 $2 $3 …

$_="Hello there, neighbor";
if(/(\S+) (\S+), (\S+)/){
	print "words were $1 $2 $3\n";
}
匹配变量存活到下次匹配成功为止。
失败的匹配不会改动上次成功匹配时捕获的内容,而成功的匹配会将它们的值重置。
  1. 自动捕获变量

字符串里实际匹配模式的部分会被自动存进$&变量里。
$&里保存的是整个匹配区段。

匹配区段之前的内容会存到“ $` ”里,而匹配区段之后的内容则会存到“ $' ”里。
另外一个理解方法是,“ $` ”保存了正则表达式引擎在找到匹配区段之前略过的部分,
而“ $' ”则保存了字符串中剩下的从未被匹配到的部分。如果将这三个字符串一次连接起来,
就一定会得到原字符串。
if("Hello there, neighbor" =~ /\s(\w+),/){
	print "That was ($`)($&)($')";
}
回显
That was (Hello)( there,)( neighbor)

自动捕获变量比捕获变量效率低些。
也可以使用如下的方法等效替代

if("Hello there, neighbor" =~ /\s(\w+),/p){
	print "That was (${^PREMATCH})(${^MATCH})(${^POSTMATCH}).\n";
}
  1. 正则表达式优先级
正则表达式特性实例
圆括号(分组或捕获)(…), (?:…), (?<LABEL>…)
量词a*, a+, a?, a{n,m}
锚位和序列abc, ^, $, \A, \b, \z, \Z
择一竖线A│B│C
原子a, [abc], \d, \1, \g{2}

一个测试程序

#!/bin/perl
while(<>){
	chomp;
	if(/YOUR_PATTERN/){
        print "Matched: ($`<$&>$')\n";
	}else{
        print "No matched: ($_)\n";
    }
}

又一个例子

while(<>){
    chomp;
    print "$&\n" if /\d+\.\d+\.\d+\.\d+/;
}
  1. 如何取出一行中所有的匹配?
echo "(21,0,0)(110,33,0)(117,1,2)" | perl -ne '@d = /\((\d+)/g; print join "\n", @d; print "\n"'
echo "(211,0,0)(110,33,0)(117,1,2)" | perl -ne 'my @re=/\((\d+)/g;foreach (@re){print "$_\n"}'

取出一行中的所有IPv4地址

#!/usr/bin/perl
while(<>){
    chomp;
    my @ip=/\d+\.\d+\.\d+\.\d+/g;
    foreach(@ip){
        print "$_\n";
    }   
}

对比shell script

grep -E -o "((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))" case1.txt

转换成数组

my @words=($line =~ /([a-z]+)/ig); #将模式绑定到$line而非$_,模式将作用于$line。

转换为哈希

my %last_name=($data =~ /(\w+)\s+(\w+)/g);
  1. 如何分割获取字符串的各个列?
$info="Caine:Michael:Actor:14,LeafyDrive";  
@personal=split(/:/,$info);  

my @fields=split /\t/, $string;
my @fields=split /\s+/,$some_input;
有时对于简单的分列需求也可以
my($name, $age, $addr, $work)=split /:/;
对于空字段可以如下处理
my(undef, $card, undef, undef, $work)=split /:/;

默认split会以空白符分割$_中的字符。
my @fields=split;

对于CSV文件,最好使用CPAN上的模块Text::CSV。

yum install -y perl-CPAN

join与split相反:

my $x=join ":",4,5,6,7; # $x 为“4:5:6:7”
  1. 用s///进行替换
s/with (\w+)/against $1's team/;
print "$_\n";

s///返回布尔值,替换成功为真,否则为假。
/g可以替换所有可能。
去除开头和结尾的空格

s/^\s+|\s+$//g

“ / ”可以使用其他字符作为分隔符,只要重复3次。

绑定操作符的例子

$file_name =~ s#^.*##s;

无损替换

my $copy=$original =~ s/\d+ ribs?/10 ribs/r;

加上/r之后,就会保留原来字符串变量中的值不变,而把替换结果作为替换操作的返回值返回。
大小写转换

s/(fred|barney)/\U$1/gi;  #不使用绑定操作符绑定到其他变量,默认就绑定到$_。

\U会将其后的所有字符转换成大写的。同理,\L会将其后的所有字符转换成小写的。可以使用\E终止大小写转换的作用。

s/(\w+) with (\w+)/\U$2\E with $1/i;

\l和\u只会影响紧跟其后的一个字符。

  1. 列表上下文中的m//
$_="Hello there, neighbor";
my($first,$second,$third)=/(\S+) (\S+), (\S+)/;
print "$second is my $third\n";

或者

echo "Hello there, neighbor" | perl -ne 'my($first,$second,$third)=/(\S+) (\S+), (\S+)/;print "$second is my $third\n"'
  1. 备份文件
    <> 结合对“ $^I ”变量赋值。
定义备份文件扩展名。
$^I = ".bak";
  1. 命令行形态的perl
$ perl -p -i.bak -w -e 's/Randall/Randal/g' fred*.dat
等效于如下代码:
#!/usr/bin/perl -w
$^I=".bak";
while(<>){
	s/Randall/Randal/g;
	print;
}

常用命令行参数

参数作用
-p生成程序片段 while(<>){ print; }
-n生成程序片段 while(<>){ }
-i在程序运行之前把 $^I 设置为备份文件后缀名
-w开启告警功能
-e后边是可执行的perl代码。代码会处于print前边。代码片段末尾可以省略分号。如果有多个-e选项,就会有多段程序代码。此时只有最后一段末尾的分号可以省略。

来个例子

$ perl -e 'print "$ENV{PATH}\n"'
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值