亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Regex > 正文

實例詳解正則表達式的高級技巧

2024-09-07 17:40:05
字體:
來源:轉載
供稿:網友

今天是錯新技術頻道小編和大家分享的實例詳解正則表達式的高級技巧,正則表達式在我們日常生活中并不是很常使用的,但是對于一些高級的運用,我們的程序員還是有待提高的。

正則表達式(Regular Expression, abbr. regex) 功能強大,能夠用于在一大串字符里找到所需信息。它利用約定俗成的字符結構表達式來發生作用。不幸的是,簡單的正則表達式對于一些高級運用,功能遠遠不夠。若要進行篩選的結構比較復雜,你可能就需要用到高級正則表達式。

本文為您介紹正則表達式的高級技巧。我們篩選出了八個常用的概念,并配上實例解析,每個例子都是滿足某種復雜要求的簡單寫法。如果你對正則的基本概念尚缺乏了解,請先閱讀 這篇文章,或者 這個教程,或者維基條目。

這里的正則語法適用于PHP,與Perl兼容。

?

1. 貪婪/懶惰

Greed

所有能多次限定的正則運算符都是貪婪的。他們盡可能多地匹配目標字符串,也就是說匹配結果會盡可能地長。不幸的是,這種做法并不總是我們想要的。因此,我們添加“懶惰”限定符來解決問題。在各個貪婪運算符后添加“?”能讓表達式只匹配盡可能短的長度。另外,修改器“U”也能惰化能多次限定的運算符。理解貪婪與懶惰的區別是運用高級正則表達式的基礎。

貪婪操作符

操作符 * 匹配之前的表達式零次或零次以上。它是一個貪婪操作符。請看下面的例子:

preg_match( '/

.*<//h1>/', '

這是一個標題。

?

這是另一個。

', $matches );

?

?

句點(.)能代表除換行符外的任意字符。上面的正則表達式匹配 h1 標簽以及標簽內的所有內容。它用句點(.)和星號(*)來匹配標簽內的所有內容。匹配結果如下:

?

這是一個標題。

這是另一個。

?

整個字串都被返回。* 操作符會連續匹配所有內容—— 甚至包括中間的 h1 閉合標簽。因為它是貪婪的,匹配整個字串是符合其利益最大化原則。

懶惰操作符

把上面的式子稍作修改,加上一個問號(?),能讓表達式變懶惰:

/

.*?<//h1>/

?

?

這樣它會覺得,只需匹配到第一個 h1 結尾標簽就完成任務了。

另一個有著類似屬性的貪婪操作符是 {n,} 。它代表之前的匹配模式重復n次或n次以上,如果沒有加上問號,它會尋找盡可能多的重復次數,加上的話,則會盡可能少重復(當然也就是“重復n次”最少)。

# 建立字串
$str = 'hihihi oops hi'
;
# 使用貪婪的{n,}操作符進行匹配
preg_match( '/(hi){2,}/', $str, $matches );? # matches[0] 將是
'hihihi'
# 使用墮化了的 {n,}? 操作符匹配
preg_match( '/(hi){2,}?/', $str, $matches );? # matches[0] 將是 'hihi'

?

2. 回返引用(Back referencing)

Back Referencing

有什么用?

回返引用(Back referencing)一般被翻譯成“反向引用”、“后向引用”、“向后引用”,個人覺得“回返引用”更為貼切。它是在正則表達式內部引用之前捕獲到的內容的方法。例如,下面這個簡單例子的目的是匹配出引號內部的內容:

# 建立匹配數組
$matches = array
();
# 建立字串
$str = ""This is a 'string'""
;
# 用正則表達式捕捉內容
preg_match( "/(/"|').*?(/"|')/", $str, $matches
);
# 輸出整個匹配字串
echo? $matches[0];

?

它會輸出:

"This is a'

顯然,這并不是我們想要的內容。

這個表達式從開頭的雙引號開始匹配,遭遇單引號之后就錯誤地結束了匹配。這是因為表達式里說:("|'),也就是雙引號(")和單引號(')均可。要修正這個問題,你可以用到回返引用。表達式/1,/2,…,/9 是對前面已捕獲到的各個子內容的編組序號,能作為對這些編組的“指針”而被引用。在此例中,第一個被匹配的引號就由/1代表。

如何運用?

將上面的例子中,后面的閉合引號替換為1:

preg_match( '/(/"|').*?/1/', $str, $matches );

這會正確地返回字串:

"This is a 'string'"

譯注思考題:

如果是中文引號,前引號和后引號不是同一個字符,怎么辦?

還記得PHP函數 preg_replace 嗎?其中也有回返引用。只不過我們沒有用 /1 … /9,而是用了 $1 … $9 … $n (此處任意數目均可)作為回返指針。例如,如果你想把所有的段落標簽

都替換成文本:

$text = preg_replace( '/

(.*?)

/',
"

$1

", $html );

?

參數$1是一個回返引用,代表段落標簽

內部的文字,并插入到替換后的文本里。這種簡便易用的表達式寫法為我們提供了一個獲取已匹配文字的簡單方法,甚至在替換文本時也能使用。

3. 已命名捕獲組(Named Groups)

當在一個表達式內多次用到回調引用時,很容易就把事情搞混淆,要弄清那些數字(1 … 9)都代表哪一個子內容是件很麻煩的事?;卣{引用的一個替代方法是使用帶名字的捕獲組(下文簡稱“有名組”)。有名組使用(?Ppattern)來設定,name代表組名,pattern是配合該有名組的正則結構。請看下面的例子:

/(?P"|').*?(?P=quote)/

上式中,quote就是組名,"|'是改組匹配內容的正則。后面的(?P=quote)是在調用組名為quote的有名組。這個式子的效果和上面的回調引用實例一樣,只不過是用了有名組來實現。是不是更加易讀易懂了?

有名組也能用于處理已匹配內容之數組的內部數據。賦予特定正則的組名也能作為所匹配到的內容在數組內部的索引詞。

preg_match( '/(?P"|/')/', "'String'", $matches );
# 下面的語句輸出“'”(不包括雙引號)
echo $matches
[1];
# 使用組名調用,也會輸出“'”
echo $matches['quote'];

所以,有名組并不只是讓寫代碼更容易,它也能用于組織代碼。

4. 字詞邊界(Word Boundaries)

Word Boundaries

字詞邊界是字串里的字詞字符(包括字母、數字和下劃線,自然也包括漢字)和非字詞字符之間的位置。其特殊之處就在于,它并不匹配某個實在的字符。它的長度是。 /b 匹配所有字詞邊界。

不幸的是,字詞邊界一般都被忽視掉了,大部分人都沒有在意他的現實意義。 例如,如果你想要匹配單詞“import”:

/import/

注意了!正則表達式有時候很調皮的。下面的字串也能和上面的式子匹配成功:

important

你或許覺得,只要在import前后加上空格,不就可以匹配這個獨立的單詞了:

/ import /

那如果遇上這種情況呢:

The trader voted for the import

當 import 這個詞在字串開頭或者結尾時,修改后的表達式仍然不能用。因此,考慮各種情況是必須的:

/(^import | import | import$)/i

別慌,還沒完呢。如果遇到標點符號了呢?就為了滿足這一個單詞的匹配,你的正則可能就需要這樣寫:

/(^import(:|;|,)? | import(:|;|,)? | import(/.|/?|/!)?$)/i

對于只匹配一個單詞來說,這樣做實在是有點大動干戈了。正因如此,字詞邊界才顯得意義重大。要適應上述要求,以及很多其他情況變種,有了字符邊界,我們所需寫的代碼只是:

//bimport/b/

上面所有情況都得到了解決。 /b 的靈活性就在于,它是一個沒有長度的匹配。它只匹配兩個實際字符之間想象出的位置。它檢查兩個相鄰字符是否是一個為單字,另一個為非單字。情況符合,就返回匹配。如果遇到了單詞的開頭或結尾, /b 會把它當成是非單詞字符對待。由于import里面的 i 仍然被看成是單詞字符,import 就被匹配出來了。

注意,與/b相對,我們還有/B,此操作符匹配兩個單字或者兩個非單字之間的位置。因此,如果你想匹配在某個單詞內部的‘hi',可以使用:

/Bhi/B

“this”、“hight”,都會返回匹配,而“hi there”則不會返回匹配。

5. 最小組團(Atomic Groups)

Advanced Operators

最小組團是無捕捉的特殊正則表達式分組。通常用來提高正則表達式的效能,也能用于消除特定匹配。一個最小組團可以用(?>pattern) 來定義,其中pattern是匹配式。

/(?>his|this)/

當正則引擎針對最小組團進行匹配時,它會跳過組團內標記的回溯位置。以單詞“smashing”為例,當用上面的正則表達式匹配時,正則引擎會先嘗試在“smashing”里尋找“his”。顯然,找不到任何匹配。此時,最小組團就發揮作用了:正則引擎會放棄所有回溯位置。也就是說,它不會嘗試再從“smashing”里查找“this”。為什么要這樣設置?因為“his”都沒有返回匹配結果,包含有“his”的 “this”當然就更匹配不了了!

上面的例子并沒有什么實用性,我們用/t?his?/ 也能達到效果。再看看下面的例子:

//b(engineer|engrave|end)/b/

?

如果把“engineering”拿去匹配,正則引擎會先匹配到“engineer”,但接下來就遇到了字詞邊界,/b,所以匹配不成功。然后,正則引擎又會嘗試在字串里尋找下一個匹配內容:engrave。匹配到eng的時候,后面的又對不上了,匹配失敗。最后,嘗試 “end”,結果同樣是失敗。仔細觀察,你會發現,一旦engineer匹配失敗,并且都抵達了字詞邊界,“engrave”和“end”這兩個詞就已經不可能匹配成功了。這兩個詞都比engineer短小,正則引擎不應該再多做無謂的嘗試。

//b(?>engineer|engrave|end)/b/

上面的替代寫法更能節省正則引擎的匹配時間,提高代碼的工作效率。

6. 遞歸(Recursion)

Recursion

遞歸(Recursion)用于匹配嵌套結構,例如括弧嵌套, (this (that)),HTML標簽嵌套

?

。我們使用(?R)來代表遞歸過程中的子模式。下面是一個匹配嵌套括弧的例子:

?

//(((?>[^()]+)|(?R))*/)/

最外層使用了反義符的括號“/(”匹配嵌套結構的開端。然后是一個多選項操作符( * | * ),可能匹配除括號外的所有字符 “(?>[^()]+)”,也可能是通過子模式“(?R)”來再次匹配整個表達式。請注意,這個操作符會盡量多地匹配所有嵌套。

遞歸的另一個實例如下:

/<([/w]+).*?>((?>[^<>]+)|((?R)))*<///1>/

以上表達式綜合運用了字符分組,貪婪操作符、回溯,以及最小化組團來匹配嵌套標簽。第一個括弧內分組([w]+)匹配出標簽名,用于接下來的應用。若找到這尖括號樣式的標簽,則嘗試尋找標簽內容的剩余部分。下一個括弧括起來的子表達式和上一個實例非常相似:要么匹配不包括尖括號的所有字符 ?>[^<>]+,要么遞歸匹配整個表達式(?R)。表達式最后的代表閉合標簽。

7. 回調(Callbacks)

Callbacks

匹配結果中的特定內容有時可能會需要某種特別的修改。要應用多重而復雜的修改,正則表達式的回調就有了用武之地。回調是用于函數preg_replace_callback中的動態修改字串的方式。你可以為preg_replace_callback指定某個函數為參數,此函數能接收匹配結果數組為參數,并將數組修改后返回,作為替換的結果。

例如,我們想將某字串中的字母全部轉變成大寫。十分不巧,PHP沒有直接轉化字母大小寫的正則操作符。要完成這項任務,就可以用到正則回調。首先,表達式要匹配出所有需要被大寫的字母:

//b/w/

上式同時使用了字詞邊界和字符類。光有這個式子還不夠,我們還需要一個回調函數:

function upper_case( $matches ) {
return strtoupper( $matches
[0] );
}

?

函數upper_case接收匹配結果數組,并將整個匹配結果轉化成大寫。 在此例中,$matches[0]代表需要被大寫化的字母。然后,我們再利用preg_replace_callback實現回調:

preg_replace_callback( '//b/w/', "upper_case", $str );

一個簡單的回調即有這般強大的力量。

8. 注釋(Commenting)

Commenting

注釋不用來匹配字串,但確實是正則表達式中最重要的部分。當正則越寫越深入,越寫越復雜,要推譯出究竟什么東西被匹配就會變得越來越困難。在正則表達式中間加上注釋,是最小化將來的迷糊和困惑的最佳方式。

要在正則表達式內部加上注釋,使用(?#comment)格式。把“comment”替換成你的注釋語句:

/(?#數字)/d/

如果你打算把代碼公之于眾,為正則表達式加上注釋就顯得尤為重要。這樣別人才能更容易看懂和修改你的代碼。和其他場合的注釋一樣,這樣做也能為你重訪自己以前寫的程序時提供方便。

考慮使用“x”或“(?x)”修改器來格式化注釋。這個修改器讓正則引擎忽略表達式參數之間的空格?!坝杏玫摹笨崭袢匀荒軌蛲ㄟ^[ ]/s,或者/ (反義符加空格)來匹配。

/
/d??? #digit
[ ]?? #space
/w+?? #word
/x

上面的代碼與下面的式子作用一樣:

//d(?#digit)[ ](?#space)/w+(?#word)/

請時刻注意代碼的可讀性。

實例詳解正則表達式的高級技巧就為各位朋友們介紹到這里了,大家是不是對這些內容也非常感興趣呢?如果你也想學習更多的知識,那就趕緊關注錯新技術頻道吧!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
69av在线视频| 日韩人在线观看| 国产日韩中文在线| 久久国产精品视频| 久久99久国产精品黄毛片入口| 欧美电影在线观看完整版| 国模精品视频一区二区三区| 亚洲免费视频观看| 国产成人亚洲精品| 国产精品吊钟奶在线| 亚洲国产精品久久久久秋霞蜜臀| 久久久99久久精品女同性| 日韩亚洲综合在线| 日日摸夜夜添一区| 日本欧美精品在线| 亚洲一区二区三区视频播放| 日韩欧美成人免费视频| 日韩在线国产精品| 欧美电影免费观看电视剧大全| 日韩中文在线不卡| 高清欧美电影在线| 欧亚精品中文字幕| 日产精品久久久一区二区福利| 久久久精品在线观看| 日韩中文字幕免费看| 亚洲日本欧美日韩高观看| 日韩视频在线免费| 亚洲激情视频网| 欧美最猛性xxxxx亚洲精品| 91精品国产色综合久久不卡98| 亚洲在线视频观看| 欧美精品videofree1080p| 欧美在线视频一二三| 欧美国产极速在线| 2019中文在线观看| 欧美中文字幕在线播放| 欧美激情网站在线观看| 久久69精品久久久久久久电影好| 久久久久久久久久久国产| 国产日韩精品一区二区| 久久躁日日躁aaaaxxxx| 国产视频精品自拍| 久久躁日日躁aaaaxxxx| 国产综合香蕉五月婷在线| 欧美日韩美女在线| 欧美激情三级免费| 国产成人精彩在线视频九色| 久久国产精品久久久久久久久久| 国产精品久久久久久久午夜| 色噜噜国产精品视频一区二区| 精品中文字幕在线观看| 97在线视频免费看| 亚洲男人天堂2024| 欧洲成人在线观看| 九色91av视频| 中文字幕亚洲精品| 欧美在线日韩在线| 午夜精品一区二区三区视频免费看| 国产成人高清激情视频在线观看| 国产精品久久久久久久久久久久久久| 精品久久久久久久大神国产| 亚洲国产精品久久久| 亚洲欧美国产高清va在线播| 亚洲人成免费电影| 永久免费精品影视网站| 成人性生交xxxxx网站| 日韩欧美成人网| 中国人与牲禽动交精品| 亚洲女人初尝黑人巨大| 欧美一级高清免费| 亚洲欧美成人网| 午夜欧美不卡精品aaaaa| 亚洲一区二区中文字幕| 日韩最新中文字幕电影免费看| 色噜噜久久综合伊人一本| 国产综合在线视频| 国产高清视频一区三区| 8090成年在线看片午夜| 久久99精品久久久久久噜噜| 亚洲美女精品成人在线视频| 一个人看的www欧美| 国产一区二区三区18| 亚洲免费电影在线观看| 日韩精品一二三四区| 欧美精品aaa| 久久激情视频免费观看| 91精品国产高清自在线看超| 日韩三级影视基地| 草民午夜欧美限制a级福利片| 狠狠躁夜夜躁人人爽超碰91| 国产欧美日韩精品在线观看| 欧美日韩另类视频| 亚洲精品一区二区三区不| 亚洲xxxx在线| 精品久久香蕉国产线看观看亚洲| 国产在线精品成人一区二区三区| 亚洲热线99精品视频| 精品在线观看国产| 97久久超碰福利国产精品…| 一区二区三区精品99久久| 国产午夜精品久久久| 国产精品91免费在线| 5278欧美一区二区三区| 91久久精品日日躁夜夜躁国产| 国产精品视频一区二区三区四| 懂色av影视一区二区三区| 丝袜亚洲欧美日韩综合| 2019亚洲男人天堂| 91社影院在线观看| 国产成人精品一区二区| 国产日韩欧美日韩| 久热精品在线视频| 国产精品va在线| 91黄色8090| 日韩精品视频在线免费观看| 日韩成人在线网站| 疯狂蹂躏欧美一区二区精品| 国产精品视频一区国模私拍| 欧美一级淫片aaaaaaa视频| 日韩av影视综合网| 九九九热精品免费视频观看网站| 国产69精品99久久久久久宅男| 97国产精品人人爽人人做| 亚洲精品国产精品国产自| 97人人做人人爱| 国产精品流白浆视频| 久精品免费视频| 国产一区二区三区视频在线观看| 大荫蒂欧美视频另类xxxx| 日日摸夜夜添一区| 国产欧美精品一区二区三区-老狼| 亚洲free性xxxx护士hd| 久久国产天堂福利天堂| 国产精品久久久久一区二区| 日韩在线视频观看| 日韩高清人体午夜| 欧美老妇交乱视频| 亚洲欧美中文在线视频| 不卡av电影院| 日韩欧美aⅴ综合网站发布| 亚洲国产日韩精品在线| 日韩国产精品视频| 久久亚洲成人精品| 久久精品影视伊人网| 91av视频在线免费观看| 成人av在线亚洲| 日本一本a高清免费不卡| 欧美xxxx18性欧美| 亚洲香蕉在线观看| 亚洲精品免费在线视频| 国产精品亚洲网站| 欧美洲成人男女午夜视频| 国产专区精品视频| 日韩在线精品视频| 亚洲精品中文字| 成人免费观看a| 久久天堂av综合合色| 最新国产精品亚洲| 福利一区福利二区微拍刺激| 欧美专区日韩视频| 欧美中文字幕在线播放| 欧美亚洲成人免费| 国产欧美精品日韩精品| 日韩中文字幕视频在线|