Perl Learning 7 The match of Regular Expression
用m//进行匹配:再上一章中,我用了双斜线的写法表示模式,比如/fred/。实际上,这是m//(pattern?match?operator,模式匹配操作符)的简写。如果我们选择双斜线作为定界符,那么我们可以省略开头的m。 用/i进行大小写无关的匹配: print "Would you like to play a game?"; chomp($_ = <STDIN>); if(/yes/i){ print "In that case,I recommend that you go bowling.n"; } 用/s匹配任意字符:?默认情况下,点号(.)无法匹配换行符,这对大多数单行匹配的情况是合适的。但如果字符串中含有换行符,而你希望点号能匹配这些换行符,那么/s修饰可以完成这个任务。它会将模式中每个点号转换成按字符集[dD]来处理,就是说会匹配任意字符。 $_ = "I saw Barneyndown at the bowling alleyn with Fredn last night.n"; if(/Barney.*Fred/s){ print "That string mentions Fred after Barney!n"; } 但有时这项特性也会带来一点问题。修饰符/s会把模式中出现的所有.都修改成能匹配任意字符,那么要是我们只想其中几个点号匹配任意字符呢?可以换用字符集[^n],也可以N 用/x加入空白符:/?-??[0-9]+?.?[0-9]*/x?原来表示空格和制表符本身的空白符就失去了意义。 / -? #一个可有可无的减号 [0-9]+ #小数点前必须出现一个或多个数字 .? #一个可有可无的小数点 [0-9]* #小数点后面的数字,有没有都没有关系 /x #字符串末尾 注意,注释部分不要使用定界符,否则会被视为模式终点 组合选项修饰符:如果需要对单词匹配使用多项修饰符,只需要把它们接在一起写在模式末尾,同时不用在意先后顺序。 锚位:默认情况下,如果给定模式不匹配字符串的开头,就会顺移到下一个字符继续尝试。而通过给定的锚位,我们可以让模式仅在字符串指定位置匹配。A锚位匹配字符串的绝对开头,如果开头位置上不匹配,是不会顺移到下一个位置继续尝试的。m{Ahttps?://}i判断字符串是否以https开头。对应地,如果要匹配字符串的绝对末尾,可以用z错位。Z允许后面出现换行符,这样人们就不必操心去掉单行内容末尾的换行符: while(<STDIN>){ print if /.pngZ/; } 单词锚位:b是单词边界锚位,它能匹配任何单词的首尾。非单词边界锚位是B,它能匹配所有b不能匹配的位置。因此,模式/bsearchB/?会匹配searches、searching等,但不匹配search 绑定操作符=~:默认情况下模式匹配的操作对象是$_,binding?operator告诉Perl,拿右边的模式来匹配左边的字符串,而不是匹配$_。 my $some_other = "I dream of betty rubble."; if($some_other =~ /brub/){ print "Aye,there's the rub.n"; } 绑定操作符的优先级相当高,没有必要用圆括号啦括住模式测试表达式。下面这一行会将匹配结果(而非该行输入的内容)存入变量:my?$like_perl?=?<STDIN>?=~?/yesb/i 捕获变量:圆括号出现的地方一般都会触发正则表达式引擎捕获匹配到的字符串 my $what = “larry”; while(<>){ if (/A($what)/){ print “We saw $what in beginning of $_”; } } 模式中有多少个捕获括号,就有多少个对应名称的捕获变量可用。在Perl里面,它们的名称就是$1和$2这样的形式。 $_ = "Hello there,hsl"; if(/s([a-zA-Z]+),/){ #捕获空白符和逗号之间的单词 print "the word was $1n"; } 捕获变量的存续期:它能存活到下次成功匹配为止,失败的匹配不会改变上次成功匹配时捕获的内容,而成功的匹配会将它们的值重置。 不捕获模式:(?:),这样就可以用$1捕获实际需要的内容: if(/(?:bronto)?saurus (steak|burger)/){ print “Fred wants a $1n”; } 命名捕获:为了避免记忆$1之类的数字变量,Perl?5.10增加了对捕获内容直接命名的写法。最终捕获到的内容会保存在特殊哈希%+里面:其中的键就是在捕获时用的特殊标签,对应的值则是被捕获的字符串。具体写法是(?<LABEL>PATTERN),其中LABEL可以自行命名 my $names = 'Fred or Barney'; if( $names =~m/(?<name1>w+) (?:and|or) (?<name2>w+)/){ print "I saw $+{name1} and $+{name2}"; } 在使用捕获标签后,反向引用的用法也要变化,可以使用g{label} 自动捕获变量:字符串里实际匹配模式的部分会被自动存进$&里,匹配区段之前的内容会存到$`里,而匹配区段之后的内容则会存到$’里。如果将这三个字符串依次连接起来,就一定会得到原来的字符串 ? 通用量词:qualifier代表前面条目的重复次数,我们还可以用{}的形式指定具体的重复次数范围。星号和量词{0,}相同,表示零次或多次。加号相当于{1,}表示一次以上。问号也可以写成{0,1}。 ? 优先级?高->低:圆括号(用于分组和捕获)->?量词(*?+{5,16})->锚位和序列(A,Z...)->?择一竖线(|)->?atoms
1. $_ = <STDIN>; if(/match/){ print "I catch match,before:$`,after: $'n"; } 2. $_ = <STDIN>; if(/[a-zA-Z]+ab/){ print " I found it"; } 3. <p style="font-family: 'Times New Roman';"></p><pre name="code" class="plain">$_ = <STDIN>; if(/([a-zA-Z]+ab)/){ print " I found $1n"; } print?"$1?contains?'$1'"; 答案给出的是: while(<STDIN>){ chomp; if(/(bw*ab)/){ print “Match: |$`<$&>$’|n”; print “$1 contains ‘$1’n”; }else{ print “No match:|$_|n”; } } 比我多写了一个else语句,强制字母开头,w覆盖的范围比我的[a-zA-Z]更广 4. $_ = <STDIN>; if(/(?<word>[a-zA-Z]+ab)/){ print " I found $+{word}n"; } print "'word' contains '$+{word}'"; 答案给出: while(<STDIN>){ chomp; if(/(?<word>bw*ab)/){ print “Match: |$`<$&>$’|n”; print “’word’ contains ‘$+{word}’n”; }else{ print “No match:|$_|n”; } } 5. $_ = <STDIN>; if(/(?<word>[a-zA-Z]+ab)(?<other5>.{0,5})/){ print " I found $+{word}n"; } print "'word' contains '$+{word}'n"; print "'Other5' is '$+{other5}'"; 答案: m/ (bw*ab) (.{0,5}) /xs 6. while(<>){ chomp; if(/sz/){ print "$&Endn"; } } 就不贴结果的截图了,毕竟都是可以跑通的~ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |