Perl中的正则表达式

(1)若模式匹配的对象是$_的内容,只要把模式写在一对斜线中就可以了:

$_="yabba dabba doo";
if(/abba/)
{
  say "It matched!";
}

(2)若要按属性匹配,只需把属性名放入\p{PROPERTY}\中即可。\p{SPACE}\可用于匹配空白符,\p{Digit}\可用于匹配数字,\p{Hex}\可用于匹配十六进制数字。若要匹配不包含特定属性的字符,将p改为大写,表示否定意义。\P{Space}\表示匹配除空白符以外的所有字符。

(3)点号(.)可用于匹配任意一个字符的通配符,换行符除外。点号只能匹配一个字符。若想 用点号匹配其本身,前加反斜线。

星号(*)可用于匹配前面条目零次或多次的。.*会匹配任意字符零次到无限多次。

加号(+)会匹配前一个条目一次以上(必须至少出现一次)。

问号(?)表示前面一个条目是可有可无的,即要么不出现,要么只出现一次

(4)圆括号可以用来对字符串分组。模式/fred+/会匹配fredddddd这样的字符串,而/(fred)+/会匹配fredfredfred这样的字符串。还可以用反向引用来引用圆括号中的模式所匹配的文字,称之为捕获组。反向引用的写法是反斜线后面接上数字。

/(.)\1/表示匹配连续出现两次的字符

也可以采用g{N}的形式表示反向引用从而避免二义性。N也可以用负数表示表示相对编号。

/(.)g{-1}/与/(.)\1/表示意义相同。下述代码会匹配成功:

use 5.010;
$_="xaa11bb";
if(/(.)(.)\g{-1}11/)
{
   say "It matched!";
}

(5)择一匹配(|)意思是要么匹配左边的内容,要么匹配右边的内容。

/fred(and|or)barney/可以用来匹配任何含有fredandbarney或fredorbarney的字符串。

(6)字符集 一组可能出现的字符,通过写在方括号内表示。它只匹配单个字符,但可以是字符集中列出的任何一个。

[abcwxyz]可以匹配这7个字符中的任意一个。

[a-zA-Z]表示可以匹配52个大小写字母中的任意一个。

/HAL-[0-9]+/可以用于匹配HAL-9000

在字符集开头的地方加上脱字符(^)可以表示这些字符串除外

[^def]会匹配这三个字符以外的任意字符

[^n\-z]则会匹配n,连字符与z以外的任何字符(包括换行符)

(7)字符集的简写

\d:表示任意一个数字的字符集的简写

若需要严格按照ASCII的范围来匹配,可在正则表达式末尾加/a

\s:匹配任意空白符(包括回车符)

\h:匹配水平空白符;\v:匹配垂直空白符

\h\v等价于\p{Space}

\R:能匹配任意断行符(避免不同才做系统的风格)

\w:"单词"字符,在ASCII语义下,匹配[a-zA-Z0-9 _];(包含下划线!!!)

他们的大写版本表示否定意义

(8)m//进行匹配

双斜线为简写

(9)模式匹配修饰符

/a:按照ASCII字符进行匹配

/i:大小写无关匹配 /yes/i等价于/(Y|y)(E|e)(S|s)/

/s:匹配任意字符。他会将模式中的每个点号转换成[\d\D]来处理。下述代码将会配成功

#!/bin/perl -w
use 5.012;
use strict;
$_="I saw Barney\ndown at the bowling alley \nwith Fred\nlast night.\n";
if(/barney.*fred/si)
{
  say "It matched!"   
}

/x:加入空白符。加上/x后模式里可以随意插入空白,此时原来表示空格和制表符本身的空白符就失去意义,可以使用转义字符或\s。Perl还会把模式中出现的注释当做空白符直接忽略。要想表示#号本身,可写成\#或[#]。注释中不要出现定界符!!!

(10)字符解释方式

/a:告诉Perl采取ASCII的方式解释字符

/u:采取Unicode方式解释字符

/l:遵从本地化语言的设定,按照对应的字符集编码作相应的处理。

/k/aai #只匹配ASCII字符K或k。两个/a表示仅仅采取ASCII方式进行大小写处理映射。

(11)锚位

通过给定锚位,让模式仅在字符串制定位置匹配

\A锚位匹配字符串的绝对开头。如果在开头位置匹配不上,将不会顺移到下一个位置继续尝试。

m{\Ahttps?://}i

\z匹配字符串的绝对末尾,包括换行符,而\Z允许后面出现换行符。若用\z进行匹配,则需去掉末尾换行符

^也可表示字符串开头锚位,$也可表示字符串结尾锚位。如果和/m一起使用,表示对多行字符的行首和行位锚位

use 5.012;
use strict;
$_="This is a wilma line barney is on another\nline barney is on another line\nbut this end in fred\nand a final dino line";
if(m\fred$\m)
{
  say "It matched!";   
}
if(m\^line\m)
{
  say "It matched!";   
}

上述代码两个正则表达式均会匹配成功

\b单词锚位,匹配单词的首位/\bfred\b/可以匹配fred、但无法匹配frederick、alfred.(此处所谓的单词是指一连串英文字母、数字与下划线的组合)。引号并不会改变单词边界。

\B非单词边界锚位。他能匹配所有\b不能匹配的位置。 模式/\bsearch\B/会匹配searches、searching、与searched,但不匹配search或research。

(12)绑定操作符=~

默认情况下模式匹配的操作对象是$_,绑定操作符高速Perl,拿右边的模式来匹配左边的字符串,而不是匹配$_.

$someother=~/\brub/会检查$someother中是否有以rub开头的单词。

(13)模式中的内插

正则表达式可以采用双引号的形式的内插。

#!/bin/perl -w
use 5.012;
use strict;
my $what="larry";
while(<>)
{
    if(/\A$what/)
    {
        say "It matched!";   
    }
}

上述代码将会匹配以larry开头的字符串。

(14)捕获变量

圆括号出现的地方一般都会触发正则表达式引擎捕获匹配到的字符串。每个捕获组包含的都是原始字符串的内容,而不是模式本身。他们的名称是$1和$2的形式。

\4反向引用的是模式匹配期间得到的结果,而$4则是模式匹配结束后所得到的捕获内容的索引。

这些变量通常能够存活到下次成功匹配为止失败的匹配不会改变上次成功匹配的内容,而成功的匹配将会使他们的值重置

Perl5.10增加了对捕获内容直接命名的方法。最终捕获的内容会保存到特殊哈希%+里面。其中的键为捕获时用的特殊标签,对应的值则是被捕获的字符串。具体写法是(?<LABEL> PATTERN)。示例如下:

#!/bin/perl -w
use 5.012;
use strict;
my $name="Fred or Barney";
if($name=~m/(?<name1>\w+) (and|or) (?<name2>\w+)/)
{
  say "I saw $+{name1} and $+{name2}";   
}

之前的反向引用\1、\g{1}也可以换成、\g{lablel};

(15)不捕获模式

允许使用圆括号分组但不进行捕获。需要在左括号的后面加上问号和冒号(?:),告知Perl这一对圆括号完全是为了分组而存在的。

if(/(?:bronto)? saurus (steak|burger)/)
{
   say "Fred want a $1\n";
}

$1将捕获(steak|burger)中的内容。

(16)自动捕获模式

$&保存的是整个匹配区段,匹配区段之前的内容会存到$`中,而匹配区段之后的内容会存到$'中。下述代码中 $`内容为“Hello”,$&匹配内容为“ there,”(一个空格、一个单词及一个逗号)。$'捕获的内容为neighbor。

#!/bin/perl -w
use 5.012;
use strict;
my $name="Hello there,neighbor";
if($name=~m/\s(\w+),/)
{
    say "That actually matched '$&'";  
    say "$`$&$'";
}

上述方式会拖慢运行速度。

可通过修饰符/p针对特定的正则表达式开启类似的自动捕获功能。此时他们的名字用${^PREMATCH}、${^MATCH}、${^POSTMATCH}表示。上述代码等价于

#!/bin/perl -w
use 5.012;
use strict;
my $name="Hello there,neighbor";
if($name=~m/\s(\w+),/p)
{
    say "That actually matched '${^MATCH}'";  
    say "${^PREMATCH}${^MATCH}${^POSTMATCH}";
}

(17)通用量词

可以使用花括号({})的形式制定具体的重复次数范围。

/a{5,15}/可重复匹配出现5到15次的字母a。若省略第二个数字但保留逗号,表示匹配次数没有上限。如果同时省略逗号与上线,表示重复固定的次数。

(18) 优先级

最高等级为圆括号("()"),用于分组和捕获。第二级是量词,即重复操作符(*+?及用花括号表示的量词)。第三级为锚位和序列(\A,\Z,\z,^,$,\b\B).第四级为择一竖线。最低级别为原子.

(19) 替换操作

s///可用于把存在变量中匹配模式的那部分内容替换成另一个字符串。(只会进行一次替换)。替换成功时返回真,替换失败时返回假。

下述程序将会输出 He's out bowling against Fred's team tonight.

#!/bin/perl -w
use 5.012;
use strict;
$_="He's out bowling with Fred tonight";
s/with (\w+)/against $1's team/;
say "$_";

(20)全局替换

/g修饰符可以让s///进行所有可能的、不重复的替换。

一种常见的替换就是缩减空白符,即将任何连续的空白转换为单一空格。

#!/bin/perl -w
use 5.012;
use strict;
$_="Input data\t may have      extra whitespace";
say "$_";
s/(\s+)/ /g;
say "$_";

上述代码输出:

Input data may have extra whitespace

Input data may have extra whitespace

仅去除开头和结尾的空白符: s/^\s+|\s+$//g

(21) 不同定界符

对于没有左右之分的字符,只要重复三次即可

s#^https://#http://#

如果使用有左右之分的成对字符,就必须使用两对,一对包住模式,一对包住替换字符串。

s{fred}{barney};

s[fred](barney);

s<fred>#barney#

(22) 无损替换

针对需要同时保留原始字符串和替换后的字符串,可采用下述方式:

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

在5.14版本中增加了/r修饰符。原来s///操作后返回的是成功替换的次数,加上/r后,就会保留原来的字符串变量的值不变,把替换结果作为操作替换的返回值返回

my $copy=$original=~ s/\d+ ribs?/10 ribs/r; (先做替换,再做赋值)

(23) 大小写转换

\U转义符会将气候所有字符串转换为大写,\L转义符会将其后所有字符转换为小写的。默认情况下,他们会影响之后全部替换的字符。可以使用\E关闭大小写转换功能。使用小写(\l,\u)时,只会影响其后紧跟的第一个字符。同时使用\u\L表示后续字符全部转换为小写,但首字母大写。

#!/bin/perl -w
use 5.014;
use strict;
$_="I saw Barney with Fred";
s/(?<name>fred|Barney)/\U$+{name}/gi;
say "$_";
s/(\w+) with (\w+)/\L$2\E with $1/gi;
say "$_";
s/(?<name>fred|Barney)/\u$+{name}/gi;
say "$_";
s/(?<name>fred|Barney)/\u\L$+{name}/gi;
say "$_";
s/(?<name>fred|Barney)/\U\l$+{name}/gi;
say "$_";

上述代码输出结果为:

I saw BARNEY with FRED

I saw fred with BARNEY

I saw Fred with BARNEY

I saw Fred with Barney

I saw fRED with bARNEY

(24) split操作符

根据给定的模式拆分字符串。用法如下:

my @fields=split /seprator/,$string;

split用拆分模式扫描指定的字符串并返回字段列表。只要模式在某处匹配成功,该出就是当前字段的借位,下一字段的开头。任何匹配模式的内容都不会出现在返回字段中。

split会保留开头出的空字段,却舍弃结尾处的空字段。

my @fileds=split /:/,":::a:b:c:::"; #得到(“”,“”,“”,“a”,“b”,"c")

若要保留结尾处的空字段,将-1作为split的第三个参数。

默认split以空白符分割$_中的字符串。在split中使用括号时,使用非捕获圆括号(?:)的写法。

(25)join函数

把片段结合成一个字符串。用法如下:

my $result=join $glue,@pieces;

join第一个参数类似胶水,可以为任意字符串,其余参数则是一串片段。join会把胶水涂进每个片段之间并返回结果字符串。

my $x=join ":",4,6,8,10,12; #$x为:4:6:8:10:12

胶水只出现在两个片段中间,不在之前也不在之后。

(26) 列表上下文中的m//

在列表上下文中使用模式匹配操作符(m//)时,如果匹配成功,则返回所有捕获变量的列表,如果匹配失败,则返回空列表。

若使用/g修饰符,则其效果是让模式能够匹配到字符串中的多个地方。

#!/bin/perl -w
use 5.014;
use strict;
my $test="fred dropped a 5 ton granite block on Mr.Slate";
my @words=($test=~/([a-z]+)/ig);
say "@words";
#将输出fred dropped a ton granite block on Mr Slate

如果模式中有多组圆括号,则每次匹配就能获取多个字符串。假设希望吧一个字符串变为哈希,可以采用:

#!/bin/perl -w
use 5.014;
use strict;
my $data="Barney Rubble fred Flintstone Wlima Flintstone";
my %last_name=($data=~/(\S+)\s+(\S+)/g);
say %last_name;

(27)非贪婪量词

非贪婪量词要求匹配的字符串越短越好,而不再是越长越好。

贪婪量词:+、*、?、{}

非贪婪量词:+?、*?、??、{}?

??虽然还是会匹配一次到零次,但会有先考虑零次的情况。

发布于 2018-03-29 22:11