發布時間:2021-09-01    所屬分類:網站建設   瀏覽:678

                          正則表達式規則、寫法(高級)


                          引言

                          image.png


                              正則表達式(regular expression)就是用一個“字符串”來描述一個特征,然后去驗證另一個“字符串”是否符合這個特征。比如 表達式“ab+” 描述的特征是“一個 'a' 和 任意個 'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合這個特征。

                              正則表達式可以用來:(1)驗證字符串是否符合指定特征,比如驗證是否是合法的郵件地址。(2)用來查找字符串,從一個長的文本中查找符合指定特征的字符串,比查找固定字符串更加靈活方便。(3)用來替換,比普通的替換更強大。

                             正則表達式學習起來其實是很簡單的,不多的幾個較為抽象的概念也很容易理解。之所以很多人感覺正則表達式比較復雜,一方面是因為大多數的文檔沒有做到由淺入深地講解,概念上沒有注意先后順序,給讀者的理解帶來困難;另一方面,各種引擎自帶的文檔一般都要介紹它特有的功能,然而這部分特有的功能并不是我們首先要理解的。


                          2. 正則表達式中的一些高級規則

                          2.1 匹配次數中的貪婪與非貪婪

                              在使用修飾匹配次數的特殊符號時,有幾種表示方法可以使同一個表達式能夠匹配不同的次數,比如:"{m,n}", "{m,}", "?", "*", "+",具體匹配的次數隨被匹配的字符串而定。這種重復匹配不定次數的表達式在匹配過程中,總是盡可能多的匹配。比如,針對文本 "dxxxdxxxd",舉例如下:


                          表達式

                          匹配結果

                          正則表達式規則、寫法(初級) 第5張 (d)(\w+)

                          "\w+" 將匹配第一個 "d" 之后的所有字符 "xxxdxxxd"

                          正則表達式規則、寫法(初級) 第5張 (d)(\w+)(d)

                          "\w+" 將匹配第一個 "d" 和最后一個 "d" 之間的所有字符 "xxxdxxx"。雖然 "\w+" 也能夠匹配上最后一個 "d",但是為了使整個表達式匹配成功,"\w+" 可以 "讓出" 它本來能夠匹配的最后一個 "d"

                              

                          由此可見,"\w+" 在匹配的時候,總是盡可能多的匹配符合它規則的字符。雖然第二個舉例中,它沒有匹配最后一個 "d",但那也是為了讓整個表達式能夠匹配成功。同理,帶 "*" 和 "{m,n}" 的表達式都是盡可能地多匹配,帶 "?" 的表達式在可匹配可不匹配的時候,也是盡可能的 "要匹配"。這 種匹配原則就叫作 "貪婪" 模式 。

                              非貪婪模式:

                              在修飾匹配次數的特殊符號后再加上一個 "?" 號,則可以使匹配次數不定的表達式盡可能少的匹配,使可匹配可不匹配的表達式,盡可能的 "不匹配"。這種匹配原則叫作 "非貪婪" 模式,也叫作 "勉強" 模式。如果少匹配就會導致整個表達式匹配失敗的時候,與貪婪模式類似,非貪婪模式會最小限度的再匹配一些,以使整個表達式匹配成功。舉例如下,針對文本 "dxxxdxxxd" 舉例:


                          表達式

                          匹配結果

                          正則表達式規則、寫法(初級) 第5張 (d)(\w+?)

                          "\w+?" 將盡可能少的匹配第一個 "d" 之后的字符,結果是:"\w+?" 只匹配了一個 "x"

                          正則表達式規則、寫法(初級) 第5張 (d)(\w+?)(d)

                          為了讓整個表達式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以讓后邊的 "d" 匹配,從而使整個表達式匹配成功。因此,結果是:"\w+?" 匹配 "xxx"


                              更多的情況,舉例如下:

                              正則表達式規則、寫法(初級) 第5張 舉例1:表達式 "<td>(.*)</td>" 與字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配時,匹配的結果是:成功;匹配到的內容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整個字符串, 表達式中的 "</td>" 將與字符串中最后一個 "</td>" 匹配。

                              正則表達式規則、寫法(初級) 第5張 舉例2:相比之下,表達式 "<td>(.*?)</td>" 匹配舉例1中同樣的字符串時,將只得到 "<td><p>aa</p></td>", 再次匹配下一個時,可以得到第二個 "<td><p>bb</p></td>"。



                          2.2 反向引用 \1, \2...

                              表達式在匹配時,表達式引擎會將小括號 "( )" 包含的表達式所匹配到的字符串記錄下來。在獲取匹配結果的時候,小括號包含的表達式所匹配到的字符串可以單獨獲取。這一點,在前面的舉例中,已經多次展示了。在實際應用場合中,當用某種邊界來查找,而所要獲取的內容又不包含邊界時,必須使用小括號來指定所要的范圍。比如前面的 "<td>(.*?)</td>"。

                              其實,"小括號包含的表達式所匹配到的字符串" 不僅是在匹配結束后才可以使用,在匹配過程中也可以使用。表達式后邊的部分,可以引用前面 "括號內的子匹配已經匹配到的字符串"。引用方法是 "\" 加上一個數字。"\1" 引用第1對括號內匹配到的字符串,"\2" 引用第2對括號內匹配到的字符串……以此類推,如果一對括號內包含另一對括號,則外層的括號先排序號。換句話說,哪一對的左括號 "(" 在前,那這一對就先排序號。

                              舉例如下:

                              正則表達式規則、寫法(初級) 第5張 舉例1:表達式 "('|")(.*?)(\1)" 在匹配 " 'Hello', "World" " 時,匹配結果是:成功;匹配到的內容是:" 'Hello' "。再次匹配下一個時,可以匹配到 " "World" "。

                              正則表達式規則、寫法(初級) 第5張 舉例2:表達式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 時,匹配結果是:成功;匹配到的內容是 "ccccc"。再次匹配下一個時,將得到 999999999。這個表達式要求 "\w" 范圍的字符至少重復5次,正則表達式規則、寫法(初級) 第5張 注意與 "\w{5,}" 之間的區別。

                              正則表達式規則、寫法(初級) 第5張 舉例3:表達式 "<(\w+)\s*(\w+(=('|").*?\4)?\s*)*>.*?</\1>" 在匹配 "<td id='td1' style="bgcolor:white"></td>" 時,匹配結果是成功。如果 "<td>" 與 "</td>" 不配對,則會匹配失??;如果改成其他配對,也可以匹配成功。



                          2.3 預搜索,不匹配;反向預搜索,不匹配

                              前面的章節中,我講到了幾個代表抽象意義的特殊符號:"^","$","\b"。它們都有一個共同點,那就是:它們本身不匹配任何字符,只是對 "字符串的兩頭" 或者 "字符之間的縫隙" 附加了一個條件。理解到這個概念以后,本節將繼續介紹另外一種對 "兩頭" 或者 "縫隙" 附加條件的,更加靈活的表示方法。

                              正向預搜索:"(?=xxxxx)","(?!xxxxx)"

                              格式:"(?=xxxxx)",在被匹配的字符串中,它對所處的 "縫隙" 或者 "兩頭" 附加的條件是:所在縫隙的右側,必須能夠匹配上 xxxxx 這部分的表達式。因為它只是在此作為這個縫隙上附加的條件,所以它并不影響后邊的表達式去真正匹配這個縫隙之后的字符。這就類似 "\b",本身不匹配任何字符。"\b" 只是將所在縫隙之前、之后的字符取來進行了一下判斷,不會影響后邊的表達式來真正的匹配。

                              正則表達式規則、寫法(初級) 第5張 舉例1:表達式 "Windows (?=NT|XP)" 在匹配 "Windows 98, Windows NT, Windows 2000" 時,將只匹配 "Windows NT" 中的 "Windows ",其他的 "Windows " 字樣則不被匹配。

                              正則表達式規則、寫法(初級) 第5張 舉例2:表達式 "(\w)((?=\1\1\1)(\1))+" 在匹配字符串 "aaa ffffff 999999999" 時,將可以匹配6個"f"的前4個,可以匹配9個"9"的前7個。這個表達式可以讀解成:重復4次以上的字母數字,則匹配其剩下最后2位之前的部分。當然,這個表達式可以不這樣寫,在此的目的是作為演示之用。

                              格式:"(?!xxxxx)",所在縫隙的右側,必須不能匹配 xxxxx 這部分表達式。

                              正則表達式規則、寫法(初級) 第5張 舉例3:表達式 "((?!\bstop\b).)+" 在匹配 "fdjka ljfdl stop fjdsla fdj" 時,將從頭一直匹配到 "stop" 之前的位置,如果字符串中沒有 "stop",則匹配整個字符串。

                              正則表達式規則、寫法(初級) 第5張 舉例4:表達式 "do(?!\w)" 在匹配字符串 "done, do, dog" 時,只能匹配 "do"。在本條舉例中,"do" 后邊使用 "(?!\w)" 和使用 "\b" 效果是一樣的。

                              反向預搜索:"(?<=xxxxx)","(?<!xxxxx)"

                              這兩種格式的概念和正向預搜索是類似的,反向預搜索要求的條件是:所在縫隙的 "左側",兩種格式分別要求必須能夠匹配和必須不能夠匹配指定表達式,而不是去判斷右側。與 "正向預搜索" 一樣的是:它們都是對所在縫隙的一種附加條件,本身都不匹配任何字符。

                              舉例5:表達式 "(?<=\d{4})\d+(?=\d{4})" 在匹配 "1234567890123456" 時,將匹配除了前4個數字和后4個數字之外的中間8個數字。由于 JScript.RegExp 不支持反向預搜索,因此,本條舉例不能夠進行演示。很多其他的引擎可以支持反向預搜索,比如:Java 1.4 以上的 java.util.regex 包,.NET 中System.Text.RegularExpressions 命名空間.



                          3. 其他通用規則

                              還有一些在各個正則表達式引擎之間比較通用的規則,在前面的講解過程中沒有提到。

                          3.1 表達式中,可以使用 "\xXX" 和 "\uXXXX" 表示一個字符("X" 表示一個十六進制數)



                          形式

                          字符范圍

                          \xXX

                          編號在 0 ~ 255 范圍的字符,比如:正則表達式規則、寫法(初級) 第5張 空格可以使用 "\x20" 表示

                          \uXXXX

                          任何字符可以使用 "\u" 再加上其編號的4位十六進制數表示,比如:正則表達式規則、寫法(初級) 第5張 "\u4E2D"



                          3.2 在表達式 "\s","\d","\w","\b" 表示特殊意義的同時,對應的大寫字母表示相反的意義


                          表達式

                          可匹配

                          \S

                          正則表達式規則、寫法(初級) 第5張 匹配所有非空白字符("\s" 可匹配各個空白字符)

                          \D

                          正則表達式規則、寫法(初級) 第5張 匹配所有的非數字字符

                          \W

                          正則表達式規則、寫法(初級) 第5張 匹配所有的字母、數字、下劃線以外的字符

                          \B

                          正則表達式規則、寫法(初級) 第5張 匹配非單詞邊界,即左右兩邊都是 "\w" 范圍或者左右兩邊都不是 "\w" 范圍時的字符縫隙


                          3.3 在表達式中有特殊意義,需要添加 "\" 才能匹配該字符本身的字符匯總


                          字符

                          說明

                          ^

                          匹配輸入字符串的開始位置。要匹配 "^" 字符本身,請使用 "\^"

                          $

                          匹配輸入字符串的結尾位置。要匹配 "$" 字符本身,請使用 "\$"

                          ( )

                          標記一個子表達式的開始和結束位置。要匹配小括號,請使用 "\(" 和 "\)"

                          [ ]

                          用來自定義能夠匹配 '多種字符' 的表達式。要匹配中括號,請使用 "\[" 和 "\]"

                          { }

                          修飾匹配次數的符號。要匹配大括號,請使用 "\{" 和 "\}"

                          .

                          匹配除了換行符(\n)以外的任意一個字符。要匹配小數點本身,請使用 "\."

                          ?

                          修飾匹配次數為 0 次或 1 次。要匹配 "?" 字符本身,請使用 "\?"

                          +

                          修飾匹配次數為至少 1 次。要匹配 "+" 字符本身,請使用 "\+"

                          *

                          修飾匹配次數為 0 次或任意次。要匹配 "*" 字符本身,請使用 "\*"

                          |

                          左右兩邊表達式之間 "或" 關系。匹配 "|" 本身,請使用 "\|"


                          3.4 括號 "( )" 內的子表達式,如果希望匹配結果不進行記錄供以后使用,可以使用 "(?:xxxxx)" 格式

                              正則表達式規則、寫法(初級) 第5張 舉例1:表達式 "(?:(\w)\1)+" 匹配 "a bbccdd efg" 時,結果是 "bbccdd"。括號 "(?:)" 范圍的匹配結果不進行記錄,因此 "(\w)" 使用 "\1" 來引用。

                          3.5 常用的表達式屬性設置簡介:Ignorecase,Singleline,Multiline,Global


                          表達式屬性

                          說明

                          Ignorecase

                          默認情況下,表達式中的字母是要區分大小寫的。配置為 Ignorecase 可使匹配時不區分大小寫。有的表達式引擎,把 "大小寫" 概念延伸至 UNICODE 范圍的大小寫。

                          Singleline

                          默認情況下,小數點 "." 匹配除了換行符(\n)以外的字符。配置為 Singleline 可使小數點可匹配包括換行符在內的所有字符。

                          Multiline

                          默認情況下,表達式 "^" 和 "$" 只匹配字符串的開始 ① 和結尾 ④ 位置。如:

                          ①xxxxxxxxx②\n
                          ③xxxxxxxxx④

                          配置為 Multiline 可以使 "^" 匹配 ① 外,還可以匹配換行符之后,下一行開始前 ③ 的位置,使 "$" 匹配 ④ 外,還可以匹配換行符之前,一行結束 ② 的位置。

                          Global

                          主要在將表達式用來替換時起作用,配置為 Global 表示替換所有的匹配。




                          4. 其他提示

                          4.1 如果想要了解高級的正則引擎還支持那些復雜的正則語法,可參見本站 DEELX 正則引擎的說明文檔。

                          4.2 如果要要求表達式所匹配的內容是整個字符串,而不是從字符串中找一部分,那么可以在表達式的首尾使用 "^" 和 "$",比如:"^\d+$" 要求整個字符串只有數字。

                          4.3 如果要求匹配的內容是一個完整的單詞,而不會是單詞的一部分,那么在表達式首尾使用 "\b",比如:正則表達式規則、寫法(初級) 第5張 使用 "\b(if|while|else|void|int……)\b" 來匹配程序中的關鍵字。

                          4.4 表達式不要匹配空字符串。否則會一直得到匹配成功,而結果什么都沒有匹配到。比如:準備寫一個匹配 "123"、"123."、"123.5"、".5" 這幾種形式的表達式時,整數、小數點、小數數字都可以省略,但是不要將表達式寫成:"\d*\.?\d*",因為如果什么都沒有,這個表達式也可以匹配成功。正則表達式規則、寫法(初級) 第5張 更好的寫法是:"\d+\.?\d*|\.\d+"。


                          4.5 能匹配空字符串的子匹配不要循環無限次。如果括號內的子表達式中的每一部分都可以匹配 0 次,而這個括號整體又可以匹配無限次,那么情況可能比上一條所說的更嚴重,匹配過程中可能死循環。雖然現在有些正則表達式引擎已經通過辦法避免了這種情況出現死循環了,比如 .NET 的正則表達式,但是我們仍然應該盡量避免出現這種情況。如果我們在寫表達式時遇到了死循環,也可以從這一點入手,查找一下是否是本條所說的原因。

                          4.6 合理選擇貪婪模式與非貪婪模式.

                          4.7 或 "|" 的左右兩邊,對某個字符最好只有一邊可以匹配,這樣,不會因為 "|" 兩邊的表達式因為交換位置而有所不同。



                          上一章節:正則表達式規則、寫法(初級)

                          打賞支付寶打賞微信打賞

                          上一篇:正則表達式規則、寫法(初級)

                          下一篇:跨境電商:利用Tiktok做Facebook廣告



                          除非注明,本站所有文章皆為本人原創,可隨意轉載但請保留鏈接或名字,謝謝!



                          相關標簽: 正則表達式昆明SEO昆山SEO蘭州SEO麗水SEO連云港SEO遼寧SEO四川SEO四會SEO太原SEO泰興SEO唐山SEO鐵嶺SEO桐城SEO

                          發表評論:

                          • 最新文章

                          • 熱門文章

                          • 隨機文章

                          SEO姜東
                            SEO姜東微信二維碼

                            常州SEO姜東


                            從事互聯網行業多年,希望分享各類互聯網、SEO理念、跨境電商,掃碼與我交流SEO


                          與我詳談SEO

                          常州SEO木木qq


                          常州SEO木木qq

                          特別推薦
                          加我的微信:SEO-jiangd詳談網絡營銷
                          一级A片中文字幕免费