簡單備忘正則表達(dá)式的原理、基本使用方法,和一些常見的優(yōu)化方法。目的看懂網(wǎng)上摘抄的正則表達(dá)式,避免使用效率過低的正則。
原理
正則文法分為確定型有限狀態(tài)自動機(jī)(DFA)和非確定型優(yōu)先狀態(tài)自動機(jī)(NFA),兩種正則匹配算法能力相同,效率有區(qū)別。
- NFA 表達(dá)式主導(dǎo)
從表達(dá)式的第一部分開始,每次檢查一部分,同時(shí)檢查當(dāng)前文本是否匹配,如果是,則繼續(xù)表達(dá)式的下一部分,如此繼續(xù),直到表達(dá)式的所有部分都能匹配。整個(gè)過程,控制權(quán)在表達(dá)式的元素之間轉(zhuǎn)換,因此被稱為表達(dá)式主導(dǎo)"。 - DFA 文本主導(dǎo)
DFA在讀入一個(gè)文本的時(shí)候,會記錄當(dāng)前有效的所有匹配的表達(dá)式位置。被掃描的字符串控制了引擎執(zhí)行過程。
構(gòu)造DFA會消耗更多的時(shí)間和內(nèi)存。但是DFA構(gòu)造好了以后執(zhí)行效率更理想。NFA在匹配的過程中,存在大量的分支和回溯。Java、JavaScript等語言使用NFA,MySQL使用DFA。
語法
- 元字符
| 字符 | 說明 |
|---|---|
| . | 除換行符外所有字符 |
| \w | 字母、數(shù)字、下劃線、漢字 |
| \d | 數(shù)字 |
| \s | 空白符 |
| \b | 匹配單詞 |
| ^ | 字符串開始 |
| $ | 字符串尾 |
- 量詞
| 語法 | 說明 |
|---|---|
| * | 重復(fù)零次或更多次 |
| + | 重復(fù)一次或更多次 |
| ? | 重復(fù)零次或一次 |
| {n} | 重復(fù)n次 |
| {n,} | 重復(fù)n次或更多次 |
| {n,m} | 重復(fù)n到m次 |
- 分組,反向引用
- 使用
()進(jìn)行分組匹配 - 使用
\1\2按順序反向引用分組內(nèi)容 - 使用
(?<name>exp)捕獲到名稱為name的分組 - 使用
(?:exp)匹配exp,不捕獲匹配分組,也不分配組號
- 匹配量詞
在正則表達(dá)式次數(shù)限定符后增加該量詞,可以指定匹配規(guī)則。
| 名稱 | 方法 | 說明 |
|---|---|---|
| Greedy:貪婪 | 默認(rèn) | 匹配最長。在貪婪量詞模式下,正則表達(dá)式會盡可能長地去匹配符合規(guī)則的字符串,且會回溯。 |
| Reluctant :非貪婪,懶惰 | ? | 匹配最短。在非貪婪量詞模式下,正則表達(dá)式會匹配盡可能短的字符串。 |
| Possessive :獨(dú)占 | + | 同貪婪一樣匹配最長。不過在獨(dú)占量詞模式下,正則表達(dá)式盡可能長地去匹配字符串,一旦匹配不成功就會結(jié)束匹配而不會回溯。 |
- 其他
- 使用
\進(jìn)行轉(zhuǎn)義 - 使用
|表示或 - 使用
[]表示區(qū)間條件
優(yōu)化
- 合理使用括號
當(dāng)要捕獲組的時(shí)候,使用非捕獲型括號(?:),這是寫策略正則最常用的優(yōu)化方法,因?yàn)槭褂??:)可以匹配想要的內(nèi)容,但不捕獲到組里,可以節(jié)省資源,提高效率。 - 盡量使用非貪婪模式
盡量使用非貪婪模式,因?yàn)樨澙纺J角闆r下,容易造成回溯。 - 使用字符組代替分支條件
使用[a-d]表示a~d之間的字母,而不是使用(a|b|c|d) - 謹(jǐn)慎用點(diǎn)號元字符,盡可能不用星號和加號這樣的任意量詞
例子: 要匹配 <12345>,其中<>中間是1-5位的數(shù)字
正常寫法: <\d*>
優(yōu)化寫法: <\d{1,5}> - 使用占有優(yōu)先量詞和固化分組
占有優(yōu)先量詞:?+ *+ ++ {m,n}+
占有優(yōu)先量詞與匹配優(yōu)先量詞很相似,只是它們從來不會交還已經(jīng)匹配的字符。
固化分組:(?>exp)
固化分組的內(nèi)容與正常的匹配并無區(qū)別,只是當(dāng)匹配完括號中的內(nèi)容后,括號中的備用狀態(tài)會全部舍去。