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

it2022-07-05  124

Perl的正则表达式支持

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

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

# 输出不包含"/bin/bash"的行 ...... if(/^((?!\/bin\/bash).)*$/){ ...... } ...... # 命令行方式 getent passwd | perl -ne 'print if /^((?!\/bin\/bash).)*$/'

这里使用到的反模式是

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

消除反向引用的奇异

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

按老的ASCII字符集来解释

if(/\s/a){ ... } 通用断行符 \R会匹配: \r\n \n

正则表达式匹配 匹配方式” m// “,其中的” / “可以使用其他字符,如##,!!,^^,(),{},<>,[]等。 当使用/时,可以省略m。

模式匹配修饰符

修饰符含义/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/ 绑定操作符=~ 默认匹配$_,通过=~来绑定匹配模式。 if($some_other =~ /\brub/){ ... } 模式中的内插 if(/\A($what)/){ ... }

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

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

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

匹配区段之前的内容会存到“ $` ”里,而匹配区段之后的内容则会存到“ $' ”里。 另外一个理解方法是,“ $` ”保存了正则表达式引擎在找到匹配区段之前略过的部分, 而“ $' ”则保存了字符串中剩下的从未被匹配到的部分。如果将这三个字符串一次连接起来, 就一定会得到原字符串。 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"; } 正则表达式优先级 正则表达式特性实例圆括号(分组或捕获)(…), (?:…), (?<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+/; } 如何取出一行中所有的匹配? 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); 如何分割获取字符串的各个列? $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” 用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只会影响紧跟其后的一个字符。

列表上下文中的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"' 备份文件 <> 结合对“ $^I ”变量赋值。 定义备份文件扩展名。 $^I = ".bak"; 命令行形态的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)