版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、931原則1正則表達式有三種形式:匹配、替換和轉換。在表 9-1 中列有三種正則表達式運算符。接下來對每一個表達式給出詳盡解釋。匹配:m/這種形式表明在/內(nèi)部的正則表達將用于匹配 = 或 !左邊的標量。為了語法上的簡化用/,略去m。替換:s/這種形式表明正則表達式將被文本 替換,為了語法的簡化用/略去s。轉換:tr/這種形式包含一系列的字符/同時把它們替換為。注意轉換并不真正是一個正則表達式,但是對于用正則表達式難于處理的數(shù)據(jù)常使用它來進行操縱。因此,tr/0-9/.組成,等字符串。通過使用(用英語講:does,與“進行匹配”同)和!(英語:doesnt,與“不匹配”同)把這些表達式捆綁到標量
2、上。作為這種類型的例子,下面我們給出六個示例正則表達式及相應的定義:$scalarName = s/a/b; # substitute the character a for b, and return true if this can happern$scalarName = m/a; # does the scalar $scalarName have an a in it?$scalarName = tr/A-Z/a-z/; # translate all capital letter with lower case ones, and return ture if this happe
3、ns$scalarName ! s/a/b/; # substitute the character a for b, and return false if this indeed happens.$scalarName ! m/a/; # does the scalar $scalarName match the character a? Return false if it does.$scalarName ! tr/0-9/a-j/; # translate the digits for the letters a thru j, and return false if this ha
4、ppens.如果我們輸入像 horned toad = m/toad/ 這樣的代碼,則出現(xiàn)圖 9-1 所示情況:另外,如果讀者正在對特定變量 $_ 進行匹配(讀者可能在while循環(huán),map或grep中使用),則可以不用!和=。因而,以下所有代碼都會合法:my elemente = ( al , a2 , a3 , a4 , a5 );foreach (elements) s/a/b/;程序使 elements 等于b1,b2b3,b4,b5。另外:while() print if (m/ERBOR/);打印所有包含 error 字符串的行:if (grep(/pattern/, lines)
5、 print the variable lines has pattern in it!n;打印所有包含模式pattern內(nèi)容的行,這直接引入下一原則。932 原則2正則表達式僅在標量上匹配。注意這里標量的重要性,如果讀者試一試如下代碼:arrayName = ( variablel, variable2);arrayName = m/variable/; # looks for variable in the array? No! use grep instead那么arrayName匹配不成功! arrayName被Perl解釋為2,于是這意味著讀者在輸入: 2 = m/variable/
6、;至少講這不能給出預想的結果。如果讀者想這樣做,輸人為:grep(m/variable/, arrayName);該函數(shù)通過arrayName中的每一個元素進行循環(huán),返回(在標量環(huán)境中)匹配的次數(shù),同時在數(shù)組環(huán)境中返回匹配元素的實際列表。933 原則3對于給定的模式串,正則表達式只匹配最早出現(xiàn)的匹配項。匹配時缺省一次只匹配或替換一次。這個原則使用稱為“回溯”的過程指出如何匹配一個給定的字符串;如果發(fā)現(xiàn)了一個局部匹配進而找到使該匹配無效的東西,正則表達式在字符串中“回溯”最小的可能數(shù)量,這個數(shù)量的字符要保證不丟失任何匹配。對于理解正則表達式正在做什么,這個原則是最有幫助的一個,同時不需要與Per
7、l一樣的形式來理解它正在做什么。假定有如下模式: Silly people do silly things if in silly moods同時想匹配如下模式: silly moods那么正則表達式引擎匹配silly,接著遇到people的P,至此,正則表達式引擎知道第一個silly不匹配,于是正則表達式引擎移到 P 且繼續(xù)尋求匹配。它接著遇到第二個silly,于是來匹配moods。然而得到的是字母 t(在thing中),于是移到 things中的 t 處,繼續(xù)進行匹配。當引擎遇到第三個silly并且盡力匹配moods時,匹配成功,匹配最后完成。所發(fā)生的情況如圖 9-2 所示。當我們遇到通配
8、符時回溯將變得更加重要。如果在同一正則表達式中有幾個通配符,且所有的通配符交織在一起,那么這里就有病態(tài)情形出現(xiàn),在這種情形下,回溯變得非常昂貴??慈缦卤磉_式: :$line = m/expression.*matching.*could.*be.*very.*expensive.*/.* 代表一個通配符,它意味著“匹配任意字符(換行符除外)零次或多次”。這個過程有可能花很長時間;如果在未匹配過的字符串末尾有可能匹配,那么引擎將發(fā)狂地回溯。為得到這方面的更多信息,請留意關于通配符方面的原則。如果讀者發(fā)現(xiàn)類似于上面的情形,那么通配符需將正則表達式分解成小功部分。換句話講,簡化自己的正則表達式。93
9、4 原則4正則表達式能夠處理雙引號字符串所能處理的任意和全部的字符。在s/運算符(s/*/),或者m/運算符m/*/的第一個分隔區(qū),位于其中的條目確實能像雙引號字符串一樣對待(帶有一些額外的附加功能,名義上的特殊正則表達式字符!后面描述)。讀者可用他們進行內(nèi)插:$variable = TEST ; $a = m/$variableaha/;和:$a = $variableaha ;二者都指向同一字符串:前者在$a中匹配字符串TESTaha后者把$a設置為字符串 TESTaha。因為正則表達式處理雙引號字符串能處理的每個字符,所以可以執(zhí)行下列操作:$expression = hello;arra
10、yName = ( elem1, elem2);$variable = m/$expression/; # this equals m/hello/;在這里,我們簡單地把$expression擴展為hello而得到m/hello/。這個技巧也可用于數(shù)組:$variable = m/arrayName/; # this equals m/elem1 elem2/;在這里,表達式等價于 m/elem1 elem2/。如果特殊變量$被設置為 |則表達式將等價于 melem | elem2,正如我們看到的,它匹配字符串的elem或者elem2。這種方法也可應用于特殊字符:$variable = m/x
11、0127/; # match binary character x01, and# octal character 27.$variable = s/ttt/; # substitute three tabs for three spaces.實際上,這里所討論的除極少數(shù)例外以外,Perl處理在m/中的過程的確像處理在雙引號中的一樣。但是有例外:有某些對正則表達式引擎有明確意義的字符。那么,如果想匹配類似于正斜杠(/)或者園括引()這樣的字符會發(fā)生什么呢?這些字符對正則表達式引取有特殊意義:因而不能使用如下語句:$variable m/usr/local/bin/; # matches /us
12、r/local/bin? NO! SYNTAX ERROR因為Perl將把/解釋為正則表達式的結束標記。這里有三種方法去匹配類似于上述特殊字符的方法。第一種方法是利用反料杠來“轉義”想匹配的任意特殊字符一包括反斜杠。因而剛才給出的例子可變?yōu)椋?path = m/usr/local/bin/;該程序盡力匹配 $path中的/usr/local/bin。第二種方法是使用一個不同的正則表達式字符。如果有許多字符要匹配,那么使用反斜杠則會變得很難看(路徑字符尤其不好)。幸運的是,Perl以一種合成形式來確決這個問題。因為在當讀者輸入m/或s/時需要給每個/加反斜杠,所以正則表達式允許讀者將正則表達式的
13、定界符(/)改為自己喜歡的任意字符。例如,我們可以使用雙引號()來避免大量的反斜杠:$variable = m/usr/local/bin; # Note the quotation marks.$variable = mhelp; # If you are going to match quotation# marks, you need to backslash them here. (as per)$variable = S $variable $variable; # works in s/too.出于好的初衷,我們在本書的前幾章使用了這一約定。如果使用作為讀者的正則表達式字符,那么在
14、用起來時它充當了好的記憶法,記住在這里所處理的實際上是字符串的變相反插入;否則,引號就遠不如斜杠常用。Perl允許使用()來書寫正則表達式:$variable = mthis works well with vi or emacs because the parens bounce;$variable = m(this also works well);$variable = s(substitute pattern) for this patternsg;這一原則對我們處理多行正則表達式非常方便。因為在這里可以不用圓括號,所以讀者可以開始把表達式作為“微型函數(shù)”對待(如果讀者有像emacs或
15、vi這樣的合理的智能編輯器),換句話講,讀者可在表達式的開始和結尾部分之間往返。第三種方法是利用函數(shù)quotemeta()來自動地加反斜杠。如果輸入如下代碼:$variable = m $scalar;則$scalar將為被插且被轉變?yōu)闃肆康闹?。這里有一個警告:任何一個特殊字符都將被正則表達式引擎影響,并且可能引起語法錯誤。因此,如果標量為:$scalar = (;那么輸入如下代碼:$variabie = m $scalar ;就等價于是說:$variable = m(,而這是一個運行時語法錯誤。如果表達式為如下形式:$scalar = quotemeta( ();則表達式會使$scalar變
16、為(,且把$scalar替換為:$variable = m ( ;這樣才可以匹配到讀者愿意匹配的字符串(。935 原則5正則表達式在求值的過程中產(chǎn)生兩種情況:結果狀態(tài)和反向引用。每次對正則表達式求值時會得到:指示正則表達式匹配字符串的次數(shù)(結果狀態(tài))。如果希望保存部分匹配,則有系列稱為反向引用的變量。接下來讓我們依次學習他們:1結果狀態(tài)結果狀態(tài)表示正則表達式匹配字符的次數(shù)。得到結果狀念的方法是在標量環(huán)境下求正則表達式的值。以下所有例子使用了這結果變量。$pattern = simple always simple;$result = ($pattern = msimple);這里,result
17、為1,因為模式simple位于simple always simPle中。同樣的,給定simple always simple:$result = ($pattern = m complex);將使result為空,因為complex不是simple always simple的子字符串,接著:$result = ($pattern = s simple complex);使result為1,因為把simple替換為complex成功了。更進一步:$pattern = simple simple;$result = ($pattern = s simple complex g);情況變得更復雜
18、。在這里,$result為2,因為在simple always simple中simple出現(xiàn)兩次,同時正則表達式的g修飾符被使用,這意味著“匹配盡可能多的次數(shù)”。(要更詳細材料參看本章后面的修飾符)。同樣地:$pattern = simple still;if ($pattern = m simple)print MATCHED!n;在if子句中使用$pattern = m simple,而該子句基本上告訴Perl,如果模式$pattern包含有子串simple則打印Matched! 。2反向引用反向引用有點復雜。假定想保存一些匹配供后用,那么為達到該目的,Perl有一個運算符(圓括號(),
19、該運算符可用于包圍讀者希望匹配的一系列給定的字符。在正則表達式中用圓括號括住某模式就是告訴解釋器“嗨,我希望保存那個數(shù)據(jù)?!?Perl解釋器再應請求,且將查找到的匹配保存在一系列特珠的變量中($1,$2,$3$65536),這些變量可用來查詢第一個、第二個、第三個等等圓括號匹配,這些變量于是可以通過查看相應的變量或在數(shù)組環(huán)境下對正則表達式進行求值而且進行訪問。例如:$text = this matches THIS not THAT ;$text = m (TH. );print $1n;在這里,字柳HIS被打印出來 Perl已經(jīng)將它們保存在$1中,以后再打印$1。 然而,該例子揭示了更多內(nèi)容
20、,例如:1)通配符(字符點(.)匹配任意字符)。如果THIS不在字符串中,模式(TH.)將欣然匹配THAT。2)正則表達式匹配一行上出現(xiàn)的第一處模式。THIS因為首先出現(xiàn),所以被匹配。同時,按缺省regexp行為,THIS將總是被匹配的第一個字符串。(可以用修飾符改變?nèi)笔≈?,詳細情況稍后介紹)。圖 9-3 表示了這一匹配過程如何進行。在圖 9-3 中每個圓括號與自已的數(shù)字變量一道運行。這里有更多的例子:$text = This is an example of backreferences;($example, $backreferences) = ($text = m (example).*
21、(backreferences) );這里又用了通配符來分開兩個文本字符串$example和$backreferences。這些字符串存放在$1和$2中,且隨后立即賦給$example和$backrefercences。該過程在圖94中說明。然而應注意的是僅當文本字符串匹配時,給$example和$bacbreference賦值的過程才發(fā)生。當文本字符串不匹配時,$example和 backreferences是空的。這里有更好的同樣的例子,該例子包含在if語句中,僅在匹配時打印$1和$2。if ($text = m (example).*(back)print $1; # prints ex
22、ample - since the first parens match the text example.print $2; # prints back - since the second parens match the text back這樣,如果正則表達式根本不匹配將發(fā)生什么?如果使用下面的模式:$text = This is an example of backreferences;$text = s (examplar).*(back) doesnt work;print $1;$1因正則表達式匹配不成功而不能被賦值。更重要地,Perl不會告訴讀者它沒有給$1賦任 何值。最后一例
23、展示了關于正則表達式的兩點重耍內(nèi)容:1)正則表達式是“要么全部要么什么也沒有”的處理,只因為back字符串在模式內(nèi)才能匹 配,所以:This is an example of backreferences并不意味著整個表達式達到匹配。因為exemplar不在字符串中,因而替換失敗。2)如果正則表達式失敗,反向引用不能得到賦值。因此,不能肯定將打印出什么內(nèi)容。當跟蹤邏輯問題時,這就是讓人吃驚的原因;且經(jīng)常是Perl gotcha。$1只是一個正則變量,并且(與Perl語法相反)如果正則表達式失敗則反向引用不被設置為“空白”。有人認為這是一個缺陷,然而另有人認為這是一個特色。不過,當分析下面的代碼
24、時第二點變得非常明顯。1 $a = bedbugs bite;2 $a = m (bedbug); # sets $1 to be bedbug.34 $b = this is nasty;5 $b = m (nasti); # does NOT set $1 (nasti is not in this is nasty ).6 # BUT $1 is still set to bedbug!7 print $1; # prints bedbug.在這種情況下,$1為字符串bedbug,因為第5行的匹配失?。∪绻M玫絥asti,好吧,那是自己的問題。這種Perl化的行為可能讓人不知所措???/p>
25、慮的是自己要當心。3使用反向引用的一般構造法如果想避免這種很平常的缺陷(讀者想得到一個匹配,但是沒有得到并且用前面的匹配為 替代而結束),在把反向引用賦給變量時只要應用下列三個構造法之一:1)短路方法。核查匹配,如果匹配發(fā)生,此時且只有此時用 &進行賦值,例如:($scalarName = m (nasti) ) $matched = $1;2)if子句。將匹配放于if子句中,如果if子句為真,此時且只有此時才為模式賦值。if ($scalarName = m (nasti) ) $matched = $1;else print $scalarName didnt match; 3)直接賦值。
26、因為可以直接把正則表達式賦給一個數(shù)值,所以可始終利用這一點。($match1, $match2) = ($scalarName = m (regexp1).*(regexp2) );讀者的所有模式的匹配代碼看起來應該與前述三個例子中的一個相似。缺少這些形式,那么就是在沒有安全保證的條件下進行編碼。如果讀者從不想有這種類型的錯誤的話,那么這些形式將節(jié)省讀者的大量時間。4在正則表達式中使用反向引用當希望使用s 運算符或者用m 運算符對一些復雜模式進行匹配很困難時,Perl提供了讀者應意識到的有用功能。這個功能就是反向引用可以用于正則表達式自身。換句話說,如果用圓括號括住一組字符,那么就可以在正則表
27、達式結束之前使用反向引用。如果想在s 的第二部分(帶下劃線)中使用反向引用,那么要使用語法$1,$2等。如果想在m 或者s 的第一部分(帶下劃線)使用反向引用,那么使用語法12等。下面是一些例子:$string = far out;$string = s (far)(out) $2 $1; # This makes string out far.我們在該例中只是將單詞far out轉換為out far。$string = sample examples;if ($string = m (amp.) ex1) print MATCHES!n; 這個例子有點復雜。第個模式(amp.)匹配字符串a(chǎn)m
28、ple。這意味轉整個模式成為字符串a(chǎn)mple example,其中帶下劃線的文本對應于1。因此,模式匹配的是 sample examples。下面是同樣風格更復雜的例子;$string = bballball;$string = s (b)1(a.)12 $1$2;讓我們詳細地看看這個例子。該例完成匹配,但是原因不是太明顯。對這個字符串的匹配有五個步驟:1)在圓括號中的第一個b匹配字符串的開頭,接著將其存放在1和$1中。2)1于是匹配字符串中的第二個b,因為與b相等,而第二個字符碰巧是b。3)(a.)匹配字符串a(chǎn)ll且被存在2和$2中。4)1匹配下一個b。5)因為2等于all所以匹配下一個且是
29、最后三個字符(all)。將他們放到一起就得到正則表達式匹配bballball,或者說是整個字符串。既然$1等于 b,$2等于all,則整個表達式:$string = bballball ;$string = s (b)1(a.)12 $1$2;(在這個例子中)轉換為如下代碼:$string = s (b)b(all)ball ball;或者用行話講,用bballball替換ball。 正則表達式看起來很像圖 9-5 所示。s 中有一些復雜的反向引用。如果理解了最后一個例子。那么讀者在理解Perl的正則表達式如何工作方面遠遠走在了前面。反向引用可能而且確實會變得更糟。5嵌套反向引用嵌套反向引用對
30、于復雜的難以用單一順序(一個字符串跟在另一個字符串后面)進行匹配的字符串作用明顯。例如下面的表達式:m (aaa)*) ;使用 * 來匹配多次出現(xiàn)的aaa:即匹配,aaa,aaaaaa,aaaaaaaaa。換句話說,Perl匹配一行中有多個3a的模式。但是這個模式不會匹配aa。假定想匹配如下的字符串:$string = softly slowly surely subtly;那么使用嵌套園括號后下面的正則表達式會匹配:$string = m (s.lys*)*) ; # note nested parens.在該例中,最外層的圓括號捕獲全部字符串:softly slowly surely su
31、btly 。最內(nèi)層的圓括號捕獲字符串的組合,這種組合是以s開頭,以ly結尾且ly后跟空格形成的。因此,正則表達式先捕獲surely,將其拋開,然后捕獲 slowly,將其拋開,然后捕獲surely,最后捕獲subtly。這里有一個問題,反向引用按什么順序出現(xiàn)?讀者可能在這個問題上很容易迷惑。是外層圓括號先出現(xiàn)呢,還是內(nèi)層的內(nèi)括圓號先出現(xiàn)?最簡單的解決辦法是記住以下三條原則:1)在表達式中,一個反向引用越在前,它對應的反向引用編號就越小。例如:$var = m (a)(b);該例中,反向引用(a)變?yōu)?1,(b)變成了$2。2)一個反向引用如果它包含范圍越廣,則它的反向引用編號就越小。例如:$v
32、ar = m (c(a(b)*)*);該例中,包含全部內(nèi)容(m (c(a(b)*)*) )的反向引用成為$1。有a嵌套在里面的表達式 m(c(a(b)*)*)成為$2。在(m(c(a(b)*)*) )中帶有b的嵌套表達式成為$3。3)在兩個規(guī)則沖突的情況下,規(guī)則1優(yōu)先。在語句$var = m (a)(b(c) 中,(a)成為$1,b(c)成為$2,(c)成為$3。因而,在這個例子中,(s.lys*)*成為$1,(s.lys*)*成為$2。注意這里有另一個問題。讓我們一起返回到剛開始的復雜的正則表達式:$string = softly slowly surely subtly$string =
33、m(s.lys*)*); # note nested parens.這里(s.lys*)*匹配什么呢?它匹配多個字符串;首先是softly,接著是slowly,再接著是surely,最后是subtly。既然(s.lys*)*匹配多個字符串,那么Perl會拋棄掉第一個匹配而使$2成為subtly。即便有這些規(guī)則,嵌套圓括號仍然可能引起混亂。要做的最好事情就是實踐。再一次用這些邏輯的不同組合去實現(xiàn)正則表達式,然后把它們交給Perl解釋器。這樣做可讓讀者明白反向引用是以什么次序被Perl解釋器進行解釋的。936 原則6正則表達式的能力的核心在于通配符和多重匹配運算符。通配符運算符允許匹配字符串中的多
34、個字符。如果正在處理二進制數(shù)據(jù),那么通配符就匹配一系列字符。多重匹配運算符可匹配零個、一個或多個字符。就講解Perl的基礎而言,到目前為止我們所使用的例子都是帶啟發(fā)性的,但功能并不是很強大。實際上,瀆者可能會用C子程序去完成它們中的任意個。Perl 正則表達式集合的強大功能來自于其匹配文本的多模式能力,(即:通過前面提到的邏輯“速記法”來描述許多不向的數(shù)據(jù)模式)。Perl正好可提供最好的速記法。1通配符通配符代表字符類。他沒有如下字符串,但不知道他們是否大寫:KumquatKristinaKentuckyKeyKeeping這種情況下,如下的Perl表達式會匹配每個單詞的第一個字符:Kk這是字
35、符類的一個例子。Perl中的所有通配符可以用括號并把想匹配的字符類放在括號中最后加上結尾括號這種方法表示。前面的通配符告訴正則表達式引擎好,我正在這里查找K或者R。如果發(fā)現(xiàn)兩者之一那么就匹配它”。下面是另一些使用通配符的例于:$scalarName = this has a digit (1) in it;$scalarName = m 0-9; # This matches any character between 0 and 9, that is matches any digit.$scalarName = this has a capital letter (A) in it;$sc
36、alarName = m A-Z; # This matches any capital letter (A-Z).$scalarName = this does not match, since the letter after the string AN is an A$scalarName = m anA;前兩個例子相當直觀,0-9匹配this has a digit(1) in it中的數(shù)字1。AZ匹配this has acapital letter(A) in it中的大寫字符A。最后一例稍有點技巧,因為在這個模式中僅有一個an,所以可能被匹配的字符唯有最后的四個字符,即an A。然
37、而,通過詢問模式anA我們已經(jīng)明確地告訴正則表達式去匹配a,接著是n,空格,最后一個為非A的字符。因而,該例中沒有完成匹配。如果給定模式為 match an A not an e,那么匹配就會完成,因為第一an被跳過后,第二個正好匹配!就像如下例子:$scalarName = This has a tab( ) or a newline in it so it matches;$scalarName = m tn # Matches either a tab or a newline.# matches since the tab is present.這個例子說明了用匹配和通配符可以做的一些
38、有趣的事情。首先,讀者已經(jīng)在字符串插入的相同字符也可以在正則表達式和用括號表示的字符類中(tn)插入。其中t匹配制表符,n匹配換行符。其次如果讀者在里的開頭部分放置一個,則通配符會匹配非字符組中的字符。同樣地,如果在 中放置-,則通配符匹配給定的范圍(在這個例子中是所有的數(shù)字0-9。所有的大寫字母(A-Z)。這些運算符還可被合并,從而得到相當特別的通配符:$a = m a-fh-z; # matches any lowercaes letter * except* g.$a = m 0-9a-zA-Z; # matches any nonword character. (i.e.,NOT# a
39、 character in 0-9, a-z or A-Z)$a = m 0-9A-Za-z; # a mistake, Does not# equal the above. Instead matches 0-9,$a = m tn; # matches a space character: tab, newline or blank).需許意的重要地方是第三個例子,在09AZaz中的插入記號是一個字面上的插入記號,而不是代表否定,原因是它在字符類的中間出現(xiàn)。因此,如果讀者想得到一個否定的字符類。那么就總是要把插入記號放在開頭。也不要忘記用。如果讀者忘記了,那么得到的將是一個字面上的文本字符
40、串,而不是一個字符類。(1)公用通配符碰巧某些通配符是公用的;當讀者每次想匹配一個數(shù)字時,可能不愿意每次都必須要輸入類似于0-9這樣的代碼。對于那些情況,Perl有幾個方便的快捷通配符,使用它們后可使編程工作容易。下面是這些邊配符以及它們代表的含義和它們對應的字符組合:d 匹配數(shù)字(字符組合0-9)。D 匹配非數(shù)(字符組合0-9)。w 匹配單詞字符(字符組合a-zA-Z0-9_)(這里下劃線算作一個單詞字符)。W 匹配非單詞字符(字符組合a-zA-Z0-9_)。s 匹配空格字符(字符組合tn)(制表符、換行符、空格)。S 匹配非空格字符(字符組合tn)。- 匹配任意字符(在某些情況下)換行符除
41、外(字符組合n)、當輸入m(.*)S時匹配任意字符。參見本章后面的修飾符。$- 盡管它實際上并不是一個通配符(它不匹配任何具體字符)但它是廣泛使用的特殊字符;如果將其放在正則表達式的尾部則它匹配“行尾”。零寬度斷言。- 盡管實際上不是一個通配符,但如果它位于正則表達式的開頭則它是匹配“行首”的特殊字符。零寬度斷言。b,B- 與$和相同;不匹配字符,但匹配單詞邊界(b)或匹配無單周邊(B)。零寬度斷言。我們從表中注意到的第一點是“點”通配符(.)。它常與多重匹配運算符一道用于在條目間充當填充者。請看以下匹配:$a = NOW is the time for all good men to com
42、e to the aid of their party;$a = m (Now).*(party); # matches, since . matches anycharacter except newlineand * means match zero or more characters.*捕獲位于Now和party中間的所有字符,匹配是成功的。(在這種環(huán)境下的“所有”意味著“零或者更多,盡可能多”。這就是所謂的貪夢(greediness);在我們后面談到多重匹配運算時再談它。)下面是通配符的一些其他例子。注意我們在=的左邊使用了單引用字符串(這是一個測試表達式的簡單方法):1 1956.
43、23 = m (d+).(d+); # $1 = 1956, $2 = 232 333e+12 = m (D+); # $1 = e+3 $hash($value) = m $(w+)$(w+); # $1 = hash, $2 = value4 $hash($value) = m $(w+)(w)*(w+)(w*); # $1 = $, $2 = hash,# $3 = $, $4 = value5 VARIABLE = VALUE = m (w+)(s*) = (s*)(w+); # $1 = VARIABLE, #$2 = ,# $3 = , $4 = VALUE6 catch as c
44、atch can = m (.*)can$; # $1 = catch as catch7 can as catch catch = mcan(.*)$ # $1 = as catch catch8 word_with_underlines word2 = m b(w+)b; # $1 = word_with_underlines每個例子中,我們使用了一個不同的通配符,在該程序中,用*表示在“一行中匹配零個或者多個通配符”。用+表示“在一行中匹配一個或者多個通配符”。這些例子中有些本身就是有用的:例5展示了使用s*來加強表達式對付散亂空格的方法;例8示例了匹配一個單詞的一般化方法;例4示范了使
45、用關鍵字匹配哈希結構的一般化方法。然而,特殊地例1不是匹配Perl數(shù)字的通用方法。但是如果給出Perl支持的所有格式,那么這會是一個十分困難的問題。我們將在后面把它作為一個問題考慮。在該表中還有一個地方需要注意:一些適配符被標記為“零寬度斷言”,我們在下面講述侖們。(2)零寬度斷言和正寬度斷言在表 9-2 中的字符就是讀者可能稱作的正寬度斷言:表 9-2 正聲明D 非數(shù)字d 數(shù)字w 單詞W 非單詞s 空格S 非空格 . 換行符以外的任意字符。這些斷言在字符串中實際上匹配一個字符。正寬度意味著匹配一個字符,同時正則表達式引擎在匹配過程中“吃掉”它們。在表 9-3 中列出的負寬度斷言。這些斷言不是
46、匹配一個字符,它們匹配的是一種條件。換句話講,cat匹配以cat開頭的字符串,但并不匹配任一給定字符。請看下面的表達式:$ziggurautString = this matches the word zigguraut;$ziggurautString = m bziggurautb;$ziggurautString = m WziggurautW;第一個例子匹配成功,因為它是在兩個非單詞字符(單詞邊界)之間查找ziggurat。而字符串滿足這種條件。第二個例子沒有完成匹配,為什么呢?因為在末尾的W是正寬度斷言,因此必須匹配一個字符。但是在行未不是字符,而是一種條件。這是重要的區(qū)別。更進一步
47、講,在第二個例子中即使實現(xiàn)了匹配,那么正則表達式引擎會消去涉及到的字符。因此,如果輸入如下代碼:$ziggurautString = This matches the word zigguraut now;$ziggurautString = s WziggurautW g;最后得到的結果是 This matches the wordnow。原因是已經(jīng)把單詞和插入的空格替換掉了。因而:零寬度斷言,例如bB能匹配沒有字符的地方。它們在匹配的過程中不會去掉任一字符。下面是關于通配符匹配的其他例子:$example = ;$example = m ddd; # match the first thr
48、ee digits it can find in the string Matches 111.$example = This is a set of words and not of numbers;$example = m of (wwwww); # Matches of words .Creates a backreference請注意最后一個例子,該列中,因為在字符串的開頭有一個of(在words前面),所以模式匹配器會匹配這個特定的of。而不會去匹配后面的of(在 numbers前面的那個)。最后一例也展示了我們將討論論的問題。這就是如果想匹配五個單詞字符的話,那么必須打印五次w,這
49、樣就很煩惱。因此、為了便于匹配長模式,Perl提供了多重匹配運算符。我們接下來討論這個問題。2多重匹配運算符PerI中有六個多重匹配運算符。主要用于避免編寫重復代碼,例如上一節(jié)提到的在一行中聲明w五次。瀆者可把它們看作是速記的捷徑。PerI的六個多重匹配運算符是:*匹配零次,一次或多次。 ?匹配一次或者多次。?匹配零次或者一次。X匹配X次。X,匹配X或者更多次。X,Y匹配X到Y次。這里有兩個等價的例子,但是哪個易讀呢?$example = This is a set of words and not of numbers;$example = m of (wwwww); # Matches o
50、f word.$example = m of (w5); # Usage of X form. Matches 5 characters,# and backreference $1 becomes the string words.讀者可能發(fā)現(xiàn)第二個例子的代碼易讀。這個例子使用了多重匹配運算符來避免寫重復、討厭的代碼。第二個例子也用符號來匹配不定數(shù)量的字符。正則表達式a*匹配”,a,aa或者aaa,或任意數(shù)量的a。也就是匹配零個或多個a,例如:$example = this matches a set of words and not of numbers;$example = m of(w
51、+);匹配的是字符串words(of(w+) eq of words),又如:$example = m of (w(2,3); # Usage of X,Y. Matches the string wor# (the first three letters of the first match it finds.matches the string wor ( of w2,3 equals of wor here)與直覺相反下面代碼中的m 子句:$example = this matches a set of words and not of numbers;$example = m of(d*);匹配該字符串,盡管我們正在用d*來查找數(shù)字。什么原因呢?因為d*表現(xiàn)為零個到多個,所以表達式匹配零個數(shù)字!然而:$example = m of(d+);將不會匹配相同的字符串,因為表達式使用的是d+而不是d*。這樣就意味著查找字符串中位于單詞of后面的一個或多個數(shù)字,而這種條件是這個字符串不具有的。3貪婪到目前為止,上面所有的例子陳述主要的一點是正則表達式引擎如何按給定的表達式匹配給定的字符串。即缺省情況下,多重匹配運算符是貪婪地?!柏澙贰痹谶@里是什么含義呢?“貪婪”意味著在缺省狀態(tài)下,Perl的多重匹配運算符能捕獲一個字符串中的最大數(shù)量的字符,同的仍然有能力來完成模式匹配。讀
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 落實酒類商品進貨查驗和索證索票制度
- 2026年昆明市尋甸縣公安局招聘警務輔助人員(37人)參考考試題庫附答案解析
- 零售戶經(jīng)營安全培訓課件
- 2026貴州貴陽市某事業(yè)單位勞務派遣工作人員招聘備考考試試題附答案解析
- 2026年上半年云南省發(fā)展和改革委員會所屬事業(yè)單位招聘人員(4人)參考考試試題附答案解析
- 2026廣西柳州事業(yè)單位招聘1111人參考考試試題附答案解析
- 2026年上半年黑龍江事業(yè)單位聯(lián)考省教育廳招聘1人備考考試試題附答案解析
- 2026年沂南縣部分事業(yè)單位公開招聘綜合類崗位工作人員28人參考考試試題附答案解析
- 2026遼寧省文物考古研究院招聘3人參考考試題庫附答案解析
- 安全生產(chǎn)保障金制度
- 小學六年級上冊數(shù)學期末測試卷及參考答案(輕巧奪冠)
- DZ∕T 0130-2006 地質礦產(chǎn)實驗室測試質量管理規(guī)范(正式版)
- (高清版)JGJT 178-2009 補償收縮混凝土應用技術規(guī)程
- 電梯日管控、周排查、月調度內(nèi)容表格
- 黑龍江省中藥飲片炮制規(guī)范及標準
- QC-提高衛(wèi)生間防水一次驗收合格率
- 江蘇省徐州市2022-2023學年高一上學期期末抽測政治試題(原卷版)
- 地基處理施工中的安全風險與防范
- 食材配送服務方投標方案(技術標)
- 人教版六年級科學上期末測試題(2份)有答案
- 食品安全全球標準BRCGS第9版內(nèi)部審核全套記錄
評論
0/150
提交評論