Perl学习笔记-2(正则表达式)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl学习笔记-2(正则表达式)相关的知识,希望对你有一定的参考价值。
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(/\\pSpace/) #带有空白字符的属性
...
if(/\\pDigit/) #数字字符
...
if(/\\pHex\\pHex/) #匹配2位十六进制数
...
if(/\\PSpace/) #非空白字符
...
- 反向引用
$_="abba";
if(/(.)\\1/)
...
消除反向引用的奇异
$_="aa11bb";
if(/(.)\\g111/) #绝对分组编号
...
相对分组编号
$_="xaa11bb";
if(/(.)(.)\\g-111/) #本尊的前一个引用
...
按老的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?, an,m |
锚位和序列 | abc, ^, $, \\A, \\b, \\z, \\Z |
择一竖线 | A│B│C |
原子 | a, [abc], \\d, \\1, \\g2 |
一个测试程序
#!/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]))"
转换成数组
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
join与split相反:
my $x=join ":",4,5,6,7; # $x 为“4:5:6:7”
- 用s///进行替换
s/with (\\w+)/against $1s 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 "$ENVPATH\\n"
以上是关于Perl学习笔记-2(正则表达式)的主要内容,如果未能解决你的问题,请参考以下文章