📄 perlreg_8rule.html
字号:
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $variable =~ m" $scalar";</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 则$scalar将为被插且被转变为标量的值。这里有一个警告:任何一个特殊字符都将被正则表达式引擎影响,并且可能引起语法错误。因此,如果标量为:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $scalar = " ({";</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 那么输入如下代码:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $variabie =~ m" $scalar" ;</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 就等价于是说:$variable =~ m"({",而这是一个运行时语法错误。如果表达式为如下形式:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $scalar = quotemeta(' ({');</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 则表达式会使$scalar变为\(\{,且把$scalar替换为:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $variable =~ m" \(\{" ;</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 这样才可以匹配到读者愿意匹配的字符串({。</P>
<B>
<P ALIGN="JUSTIFY"> </P>
<P ALIGN="JUSTIFY"><a name="5"></a>9.3.5 原则5</P>
</B>
<P ALIGN="JUSTIFY"> 正则表达式在求值的过程中产生两种情况:结果状态和反向引用。</P>
<P ALIGN="JUSTIFY">每次对正则表达式求值时会得到:</P>
<P ALIGN="JUSTIFY"> .指示正则表达式匹配字符串的次数(结果状态)。</P>
<P ALIGN="JUSTIFY"> .如果希望保存部分匹配,则有—系列称为反向引用的变量。</P>
<P ALIGN="JUSTIFY"> 接下来让我们依次学习他们:</P>
<P ALIGN="JUSTIFY"> 1.结果状态</P>
<P ALIGN="JUSTIFY"> 结果状态表示正则表达式匹配字符的次数。得到结果状念的方法是在标量环境下求正则表达式的值。以下所有例子使用了这—结果变量。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> $pattern = ' simple always simple';</P>
<P ALIGN="JUSTIFY"> $result = ($pattern =~ m"simple");</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 这里,result为1,因为模式simple位于simple always simPle中。同样的,给定simple always simple:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $result = ($pattern =~ m" complex");</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 将使result为空,因为complex不是simple always simple的子字符串,接着:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $result = ($pattern =~ s" simple" complex");</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 使result为1,因为把simple替换为complex成功了。更进一步:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $pattern = ' simple simple';</P>
<P ALIGN="JUSTIFY"> $result = ($pattern =~ s" simple" complex" g);</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 情况变得更复杂。在这里,$result为2,因为在simple always simple中simple出现两次,同时正则表达式的g修饰符被使用,这意味着“匹配尽可能多的次数”。(要更详细材料参看本章后面的修饰符)。同样地:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $pattern = ' simple still';</P>
<P ALIGN="JUSTIFY"> if ($pattern =~ m" simple")</P>
<P ALIGN="JUSTIFY"> {</P>
<P ALIGN="JUSTIFY"> print " MATCHED!\n";</P>
<P ALIGN="JUSTIFY"> }</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 在if子句中使用$pattern =~ m" simple",而该子句基本上告诉Perl,如果模式$pattern包含有子串simple则打印Matched! 。</P>
<P ALIGN="JUSTIFY"> 2.反向引用</P>
<P ALIGN="JUSTIFY"> 反向引用有点复杂。假定想保存一些匹配供后用,那么为达到该目的,Perl有一个运算符(圆括号()),该运算符可用于包围读者希望匹配的一系列给定的字符。</P>
<P ALIGN="JUSTIFY"> 在正则表达式中用圆括号括住某模式就是告诉解释器“嗨,我希望保存那个数据。” Perl解释器再应请求,且将查找到的匹配保存在一系列特珠的变量中($1,$2,$3…$65536),这些变量可用来查询第一个、第二个、第三个等等圆括号匹配,这些变量于是可以通过查看相应的变量或在数组环境下对正则表达式进行求值而且进行访问。例如:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $text = " this matches ' THIS' not 'THAT' ";</P>
<P ALIGN="JUSTIFY"> $text =~ m" ('TH..' )";</P>
<P ALIGN="JUSTIFY"> print " $1\n";</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"> 在这里,字柳HIS被打印出来 —— Perl已经将它们保存在$1中,以后再打印$1。 然而,该例子揭示了更多内容,例如:</P>
<P ALIGN="JUSTIFY"> 1)通配符(字符点(.)匹配任意字符)。如果THIS不在字符串中,模式(TH..)将欣然匹配</P>
<P ALIGN="JUSTIFY">THAT。</P>
<P ALIGN="JUSTIFY"> 2)正则表达式匹配一行上出现的第一处模式。THIS因为首先出现,所以被匹配。同时,按缺省regexp行为,THIS将总是被匹配的第一个字符串。(可以用修饰符改变缺省值,详细情况稍后介绍)。</P>
<P ALIGN="JUSTIFY">图 9-3 表示了这一匹配过程如何进行。</P>
<P ALIGN="JUSTIFY"> 在图 9-3 中每个圆括号与自已的数字变量一道运行。</P>
<P ALIGN="CENTER"><IMG SRC="images/Image4.jpg" WIDTH=288 HEIGHT=268></P>
<P ALIGN="JUSTIFY">这里有更多的例子:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> $text = ' This is an example of backreferences';</P>
<P ALIGN="JUSTIFY"> ($example, $backreferences) = ($text =~ m" (example).*(backreferences)" );</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">这里又用了通配符来分开两个文本字符串$example和$backreferences。这些字符串存放在$1和$2中,且随后立即赋给$example和$backrefercences。该过程在图9—4中说明。</P>
<P ALIGN="CENTER"><IMG SRC="images/Image5.jpg" WIDTH=463 HEIGHT=270></P>
<P ALIGN="JUSTIFY"> 然而应注意的是仅当文本字符串匹配时,给$example和$bacbreference赋值的过程才发生。当文本字符串不匹配时,$example和backreferences是空的。这里有更好的同样的例子,该例子包含在if语句中,仅在匹配时打印$1和$2。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="JUSTIFY"> if ($text =~ m" (example).*(back)")</P>
<P ALIGN="JUSTIFY"> {</P>
<P ALIGN="JUSTIFY"> print $1; # prints ' example' -- since the first parens match the text example.</P>
<P ALIGN="JUSTIFY"> print $2; # prints ' back' -- since the second parens match the text back</P>
<P ALIGN="JUSTIFY"> }</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY">这样,如果正则表达式根本不匹配将发生什么?如果使用下面的模式:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1></font></B><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> $text = ' This is an example of backreferences';</P>
<P ALIGN="JUSTIFY"> $text =~ s" (examplar).*(back)" doesn't work";</P>
<P ALIGN="JUSTIFY"> print $1;</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> $1因正则表达式匹配不成功而不能被赋值。更重要地,Perl不会告诉读者它没有给$1赋任 何值。最后一例展示了关于正则表达式的两点重耍内容:</P>
<P ALIGN="JUSTIFY"> 1)正则表达式是“要么全部要么什么也没有”的处理,只因为back字符串在模式内才能匹 配,所以:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> This is an example of backreferences'</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 并不意味着整个表达式达到匹配。因为exemplar不在字符串中,因而替换失败。</P>
<P ALIGN="JUSTIFY"> 2)如果正则表达式失败,反向引用不能得到赋值。因此,不能肯定将打印出什么内容。当跟踪逻辑问题时,这就是让人吃惊的原因;且经常是Perl
gotcha。$1只是一个正则变量,并且(与Perl语法相反)如果正则表达式失败则反向引用不被设置为“空白”。有人认为这是一个缺陷,然而另有人认为这是一个特色。不过,当分析下面的代码时第二点变得非常明显。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> 1 $a = ' bedbugs bite';</P>
<P ALIGN="JUSTIFY"> 2 $a =~ m" (bedbug)"; # sets $1 to be bedbug.</P>
<P ALIGN="JUSTIFY"> 3</P>
<P ALIGN="JUSTIFY"> 4 $b = ' this is nasty';</P>
<P ALIGN="JUSTIFY"> 5 $b =~ m" (nasti)"; # does NOT set $1 (nasti is not in '
this is nasty' ).</P>
<P ALIGN="JUSTIFY"> 6 # BUT $1 is still set to bedbug!</P>
<P ALIGN="JUSTIFY"> 7 print $1; # prints ' bedbug'.</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 在这种情况下,$1为字符串bedbug,因为第5行的匹配失败!如果希望得到nasti,好吧,那是自己的问题。这种Perl化的行为可能让人不知所措。考虑的是自己要当心。</P>
<P ALIGN="JUSTIFY"> 3.使用反向引用的一般构造法</P>
<P ALIGN="JUSTIFY"> 如果想避免这种很平常的缺陷(读者想得到一个匹配,但是没有得到并且用前面的匹配为 替代而结束),在把反向引用赋给变量时只要应用下列三个构造法之一:</P>
<P ALIGN="JUSTIFY"> 1)短路方法。核查匹配,如果匹配发生,此时且只有此时用' &&'进行赋值,例如:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> ($scalarName =~ m" (nasti)" ) {$matched = $1;}</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 2)if子句。将匹配放于if子句中,如果if子句为真,此时且只有此时才为模式赋值。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> if ($scalarName =~ m" (nasti)" ) {$matched = $1;}</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> else {print "$scalarName didn't match"; }</P>
<P ALIGN="JUSTIFY"> 3)直接赋值。因为可以直接把正则表达式赋给一个数值,所以可始终利用这一点。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> ($match1, $match2) = ($scalarName =~ m" (regexp1).*(regexp2)"
);</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 读者的所有模式的匹配代码看起来应该与前述三个例子中的一个相似。缺少这些形式,那么就是在没有安全保证的条件下进行编码。如果读者从不想有这种类型的错误的话,那么这些形式将节省读者的大量时间。</P>
<P ALIGN="JUSTIFY"> 4.在正则表达式中使用反向引用</P>
<P ALIGN="JUSTIFY"> 当希望使用s" " "运算符或者用m" "运算符对一些复杂模式进行匹配很困难时,Perl提供了读者应意识到的有用功能。这个功能就是反向引用可以用于正则表达式自身。换句话说,如果用圆括号括住一组字符,那么就可以在正则表达式结束之前使用反向引用。如果想在s"
" "的第二部分(带下划线)中使用反向引用,那么要使用语法$1,$2等。如果想在m" "或者s" " "的第一部分(带下划线)使用反向引用,那么使用语法\1\2等。下面是一些例子:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> $string = ' far out';</P>
<P ALIGN="JUSTIFY"> $string =~ s "(far)(out)" $2 $1"; # This makes string ' out
far'.</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 我们在该例中只是将单词far out转换为out far。</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> $string = ' sample examples';</P>
<P ALIGN="JUSTIFY"> if ($string =~ m" (amp..) ex\1") {print " MATCHES!\n"; }</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 这个例子有点复杂。第—个模式(amp..)匹配字符串ample。这意味转整个模式成为字符串ample example,其中带下划线的文本对应于\1。因此,模式匹配的是
sample examples。</P>
<P ALIGN="JUSTIFY"> 下面是同样风格更复杂的例子;</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> $string = ' bballball';</P>
<P ALIGN="JUSTIFY"> $string =~ s" (b)\1(a...)\1\2" $1$2";</P>
</font></B><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>
<P ALIGN="JUSTIFY"> 让我们详细地看看这个例子。该例完成匹配,但是原因不是太明显。对这个字符串的匹配有五个步骤:</P>
<P ALIGN="JUSTIFY"> 1)在圆括号中的第一个b匹配字符串的开头,接着将其存放在\1和$1中。</P>
<P ALIGN="JUSTIFY"> 2)\1于是匹配字符串中的第二个b,因为与b相等,而第二个字符碰巧是b。</P>
<P ALIGN="JUSTIFY"> 3)(a..)匹配字符串all且被存在\2和$2中。</P>
<P ALIGN="JUSTIFY"> 4)\1匹配下一个b。</P>
<P ALIGN="JUSTIFY"> 5)因为\2等于all所以匹配下一个且是最后三个字符(all)。</P>
<P ALIGN="JUSTIFY"> 将他们放到一起就得到正则表达式匹配bballball,或者说是整个字符串。既然$1等于' b',$2等于all,则整个表达式:</P>
</FONT><B><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>
<P ALIGN="JUSTIFY"> $string = ' bballball' ;</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -