Learning Perl 学习笔记 Ch8 正则表达式(二)用正则表达式进行匹配

  1. 正则表达式匹配中的双斜线定界符//其实是m //的简写,就像给列表赋值的qw // 一样,m //也可以写成m {}, m (), m <>, m % %,但只有m //可以简写成//
    如果使用了双斜线// 或者尖括号< >做定界符,在模式中如果要匹配它们自身时,即使它们并不是正则表达式的元字符,也需要反斜线转义以避免Perl混淆,提早结束模式。
    demo8-1
#!/usr/bin/perl
$_ = "http://www.baidu.com";
if(m {http://}){
    print "matched m {http://}\n";
}

if(m /http:\/\//){
    print "matched m /http:\\/\\//\n";
 }

用花括号{}做定界符时模式内的斜线不需要转义,但是用斜线/做定界符时,模式内的斜线就要转义

./demo8-1
matched m {http://}
matched m /http:\/\//
  1. 在正则表达式的模式后用修饰符可以改变模式匹配的默认行为,有以下几种:
    /i:不区分大小写
    /s:让.匹配任意字符(默认.不匹配换行符)
    /x:让模式里的空格和制表符不参与匹配(但是\s依然能匹配空格和制表符),目的在于允许模式中随意添加空白,以更利于阅读

修饰符
demo8-2

#!/usr/bin/perl
$_ = "ABC DEF GHI";
print $_."\n";
if(/abc def ghi/){
    print "matched:/abc def ghi/\n";
}
if(/abc def ghi/i){
    print "matched:/abc def ghi/i\n";
}
if(/abc def ghi/ix){
    print "matched:/abc def ghi/ix\n";
}
if(/abc\sdef\sghi/ix){
    print "matched:/abc\\sdef\\sghi/ix\n";
}

使用/x修饰符后,模式里的空格失效,但是\s依然可以匹配

./demo8-2
ABC DEF GHI
matched:/abc def ghi/i
matched:/abc\sdef\sghi/ix
  1. 锚位用来限定模式匹配的位置
  • ^限定匹配位置在字符串的开头(^在字符集[]里也有使用,表示字符集的补集)
  • $限定匹配位置在字符串的结尾
    demo8-3
#!/usr/bin/perl
$_ = "abc\n";
if(/^abc$/){
    print "matched\n";
}

$同时匹配字符串结尾和字符串结尾的换行符\n

./demo8-3
matched

锚位^$默认是匹配字符串的开头和结尾,字符串可能还有多个换行符,修饰符/m可以让^$只匹配到每行的开头的结尾


\b\B匹配单词和非单词首尾(单词在Perl中指连续的字母[a-zA-Z]、数字[0-9]和下划线_),也就是说,\b会匹配\w\W\W\w,而\B会匹配\W\W\w\w
demo8-4

#!/usr/bin/perl
$_ = "zhangsan1999_ zhang_san_1999";
print $_."\n";
if(/\bzhangsan1999_\b/){
    print "matched \\bzhangsan1999_\\b\n";
}

if(/\bzhang\B_\Bsan_\B1999\b/){
    print "matched \\bzhang\\B_\\Bsan_\\B1999\\b\n";
}
./demo8-4
zhangsan1999_ zhang_san_1999
matched \bzhangsan1999_\b
matched \bzhang\B_\Bsan_\B1999\b
  1. 正则表达式的默认行为是用模式匹配$_中的字符串,但可以用绑定符号=~改变这一行为,用=~右边的模式,匹配=~左边的字符串
    demo8-5
#!/usr/bin/perl
$new_string = "Today is wonderful!";
if($new_string =~ m{Today is wonderful!}){
    print "matched!\n";
}
./demo8-5
matched!
  1. 正则表达式的模式里可以内插标量变量,但需要小心标量里可能存在的元字符
    demo8-6
#!/usr/bin/perl
$_ = "I'm fred";
print $_."\n";
$bettyorfred = "betty|fred";
if(/^$bettyorfred/){
    print "matched ^betty|fred\n";
}
if(/^($bettyorfred)/){
    print "matched ^(betty|fred)\n";
}

^betty|fred在字符串开头位置匹配betty或在字符串任意位置匹配fred
^(betty|fred)在字符串开头位置匹配bettyfred

./demo8-6
I'm fred
matched ^betty|fred
  1. 正则表达式模式中的圆括号()不仅可以用来实现分组,也可以实现捕获功能,捕获是指把当前圆括号内模式匹配到的内容暂时存储起来的功能,捕获记录的是模式匹配到的字符串,而不是模式本身,如果没有匹配的字符串,则对应的记录就为空
    demo8-7
#!/usr/bin/perl
$_ = "Fred fred";
if(/([a-zA-Z])(red) f\2/){
    print "$1red matched\n";
}

捕获用$1 $2 ...来记录多个分组的捕获结果,和反向引用\1 \2 ...不同的是,捕获功能是在正则匹配结束之后把捕获的结果存储在预定义的变量里,而反向引用是在正则表达式的模式内引用已经匹配的结果,超出正则表达式模式匹配的范围,反向引用就失去了它的意义,因为反向引用的语法只存在于正则表达式内,在Perl语言中,是没有\1 \2 ...这样的语法的。

./demo8-7
Fred matched

捕获变量$1 $2 ...生命周期从本次匹配成功开始到下次匹配成功为止,也就是说,失败的匹配不会改变上次成功匹配捕获的值,而成功的匹配会将它们重置为新的捕获值
demo8-8

#!/usr/bin/perl
$_ = "abc def";
if(/(c d)/){
    print "match:$1\n";
}
$_ =~ /(a_b)/;
print "match:$1\n";
$_ =~ /(bc de)/;
print "match:$1\n";

第一次匹配成功后$1里是c d,第二次匹配失败,$1里的内容没有改变,第三次匹配成功,$1里的内容变成了bc de

./demo8-8
match:c d
match:c d
match:bc de

所以,如果想要在匹配之后继续使用匹配的内容,最好的方式就是及时把捕获的内容保存在自己定义的变量里


捕捉功能也可以手动关闭,只需要在圆括号开始的位置键入?:这样该圆括号只用于分组,而不会把捕获的内容存入对应的捕获变量中去
demo8-9

#!/usr/bin/perl
$_ = "This is a test string";
if(/^(That|This) .* (str)\w*/){
    print "I only focused $2\n";
}
if(/^(?:That|This) .* (str)\w*/){
    print "I only focused $1\n";
}

我只需要打印匹配到的str字段,而不需要把$1预留给我不关注的第一个分组匹配到的是That还是This

./demo8-9
I only focused str
I only focused str

更进一步,我们还可以脱离$1, $2 ...这些编号的束缚,Perl 5.10引入了命名捕捉可以给要捕获的内容,分配一个名字。Perl将采用哈希的方式存储捕获的结果,哈希表%+默认用来保存正则捕获的结果,其中键是命名,值是捕获的字符串
使用命名捕捉的方式是在圆括号内的开头写上 g<NAME>,NAME就是自定义的名字,由于采用了哈希,所以名称不能重复。
demo8-10

#!/usr/bin/perl
$_ = "This is a test";
if(/(This|That) (?<be>is|was) (?<one>a|an) (test)/){
    print "This $+{be} $+{one} test\n";
}
./demo8-10
This is a test

Perl有趣的特性在于,使用了命名捕捉之后,不仅在捕获的功能里可以用,在反向引用的功能中也可以引用,用\g{NAME}\k{NAME}(二者等价)取代\g{1}来表示对应的分组
demo8-11

#!/usr/bin/perl
$_ = "gred's name is gred";
if(/^(?<gname>gred)'s name is \g{gname}$/){
    print "matched!\n";
}
./demo8-11
matched!

Perl还提供了自动捕捉变量功能
demo8-12

#!/usr/bin/perl
if("1Monday 2Tuesday 3Wednesday 2TuesDay 4Thursday" =~ /Tuesday/){
    print "1Monday 2Tuesday 3Wednesday 2TuesDay 4Thursday\n";
    print "\$`=$`\n";
    print "\$&=$&\n";
    print "\$'=$'\n";
}

$&保存第一次匹配到的字符串内容
$`保存$&之前的字符串内容
$'保存$&之后的字符串内容

./demo8-12
1Monday 2Tuesday 3Wednesday 2TuesDay 4Thursday
$`=1Monday 2
$&=Tuesday
$'= 3Wednesday 2TuesDay 4Thursday
  1. 模式中的量词代表前置条目的重复次数
    {X}:匹配X次(超过X个会只匹配前X个)
    {M,N}:至少匹配M次,至多匹配N次
    {M,}:至少匹配M次
    (,N):至多匹配N次
    {0,}*:匹配任意次
    {1,}+:至少匹配1次
    {0,1}?:不匹配或至多匹配一次
  2. 模式测试程序
    demo8-13
#!/usr/bin/perl
while(<>){
    chomp;
    if(/PATTERN/){
        print "Matched:|$`<$&>$'|\n";
    } else{
        print "No Match:|$_|\n";
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容