下面為大家帶來一篇淺談JS正規表示式的RegExp物件和括號的使用。內容還挺不錯的,現在就分享給大家,也給大家做個參考。
RegExp物件的建立:
常規的正規表示式的建立可用直接量,即斜線「/」括起來的字符。但在要求參數變化的環境下,RegExp()建構子是更好的選擇:
var reg1 = /'\w '/g;
var reg2 = new RegExp(' \'\\w \'','g');
對比兩種建立方式,RegExp中的第一個參數為要建立的正規字串,一方面注意,因為不是直接量的表示形式,因此不用斜槓「 / 」括起來了;而是字串中必須要對引號「 ' 」和轉義符號「 \ 」進行二次轉義。
此外,無論是直接量或RegExp()建構函數,都是產生了新的RegExp對象,並將其賦值給變數。
match()與exec()的異同:
#match和exec是正規表示式符合字串的常用方法。兩者實現的功能差不多,有些細微的差別:
1、使用方式
match是字串包裝物件的方法,用法:String.match(RegExp);
exec是正規表示式物件的方法,用法:RegExp.exec(String);
2、傳回的結果
當RegExp沒有設定全域標誌"g" 時:
兩者的回傳結果相同。即無符合值時傳回null,有符合值時傳回一個陣列(令array)。 array[0]為符合的字串,array[1]、array[2]…則對應為正規表示式中圓括號匹配的子字串$1、$2…。同時陣列帶有兩個屬性,array.index表示符合字串的初始位置,array.input表示正在檢索的字串。
當RegExp有設定全域標誌 "g" 時:
match在有值時傳回一個陣列array。數組的每項依次表示匹配到的所有的字串,因此不再有圓括號匹配的子字串了。此時陣列沒有index屬性和input屬性。
exec則與沒有全域標示 "g" 的表現無異。此時傳回的是陣列array,array[0]為目前符合的字串,array[1],array[2]…則為目前符合下的圓括號相符的字串。此時要注意RegExp物件的lastIndex屬性,表示原始字串中符合的字串末端的後一個位置。當沒有進一步的配對結果時,lastIndex屬性置0。因此,可用lastIndex的循環找出所有的符合字串。
支援多次符合的方式:
js 程式碼
var testStr = "now test001 test002"; var re = /test(\d+)/ig; var r = ""; while(r = re.exec(testStr)) { alert(r[0] + " " + r[1]); }
此外也可以用testStr.match(re),但是這樣的話就不能有g的選項,而且只能得到第一個匹配。
1. 正規表示式規則
1.1 普通字元
字母、數字、漢字、底線、以及後邊章節中沒有特殊定義的標點符號,都是"普通字符"。表達式中的普通字符,在匹配一個字串的時候,匹配與之相同的一個字符。
範例1:表達式"c",在匹配字串"abcde" 時,匹配結果是:成功;匹配到的內容是:"c";匹配到的位置是:開始於2,結束於3。 (註:下標從0開始還是從1開始,因當前程式語言的不同而可能不同)
舉例2:表達式"bcd",在匹配字串"abcde" 時,匹配結果是:成功;配對到的內容是:"bcd";匹配到的位置是:開始於1,結束於4。
1.2 簡單的轉義字符
一些不便書寫的字符,採用在前面加 "/" 的方法。這些字符其實我們都已經熟知了。
表達式 | |
##/r, /n | 代表回車與換行符號 |
/t | 製表符 |
還有其他一些在後邊章節中有特殊用處的標點符號,在前面加上 "/" 後,就代表該符號本身。例如:^, $ 都有特殊意義,如果要想匹配字串中 "^" 和 "$" 字符,則表達式就需要寫成 "/^" 和 "/$"。
表達式 | |
##/^ | 符合^ 符號本身 |
/$ | 符合$ 符號本身 |
/.
符合小數點(.)本身
範例1:表達式"/$d",在匹配字串"abc$de" 時,匹配結果是:成功;匹配到的內容是:"$d";匹配到的位置是:開始於3,結束於5。 | 1.3 能夠與'多種字元' 匹配的表達式 | #正規表示式中的一些表示方法,可以匹配'多種字元' 其中的任何一個字元。例如,表達式 "/d" 可以符合任意一個數字。雖然可以匹配其中任意字符,但只能是一個,不是多個。這就好比玩撲克牌時候,大小王可以代替任一張牌,但只能代替一張牌。
表達式 | |
##/d | |
/w |
/s
包括空格、製表符、換頁符號等空白字元的其中任一個
. | 小數點可以符合除了換行符號(/n)以外的任一字元 |
舉例1:表達式"/d/d",在匹配"abc123" 時,匹配的結果是:成功;匹配到的內容是:"12";匹配到的位置是:開始於3,結束於5。 | 範例2:表達式"a./d",在匹配"aaa100" 時,匹配的結果是:成功;匹配到的內容是:"aa1";匹配到的位置是:開始於1,結束於4。 1.4 自訂能夠匹配 '多種字符' 的表達式 |
表達式 | |
##[ab5@] |
範例1:表達式"[bcd][bcd]" 匹配"abc123" 時,匹配的結果是:成功;匹配到的內容是:"bc";匹配到的位置是:開始於1,結束於3。
範例2:表達式"[^abc]" 匹配"abc123" 時,匹配的結果是:成功;匹配到的內容是:"1";匹配到的位置是:開始於3,結束於4。
1.5 修飾符合次數的特殊符號
前面章節講到的表達式,無論是只能符合一種字元的表達式,或是可以符合多種字符其中任意一個的表達式,都只能匹配一次。如果使用表達式再加上修飾符合次數的特殊符號,那麼不用重複書寫表達式就可以重複配對。
使用方法是:"次數修飾"放在"被修飾的表達式"後邊。例如:"[bcd][bcd]" 可以寫成 "[bcd]{2}"。
表達式 | #作用 |
{n} | 表達式重複n次,例如:"/w{2}" 相當於"/w/w";"a{5}" 相當於"aaaaa " |
{m,n} | #表達式至少重複m次,最多重複n次,例如: "ba{1,3}"可以符合"ba"或"baa"或"baaa" |
#{m,} | 表達式至少重複m次,例如:"/w/d{2,}"可以符合"a12","_456","M12344"... |
#? | 匹配表達式0次或1次,相當於{0,1},例如:"a[cd]?"可以符合" a","ac","ad" |
表達式至少出現1次,相當於{ 1,},例如:"a b"可以匹配"ab","aab","aaab"... |
範例1:表達式"/d /.?/d*" 在符合"It costs $12.5" 時,配對的結果是:成功;符合的內容是: "12.5";配對到的位置是:開始於10,結束於14。
1.6 其他一些代表抽象意義的特殊符號 | ##有些符號在表達式中代表抽象的特殊意義:|
作用 | |
與字串開始的地方匹配,不匹配任何字元 | |
##與字串結束的地方匹配,不匹配任何字元 |
進一步的文字說明仍然比較抽象,因此,舉例幫助大家理解。
範例1:表達式 "^aaa" 在符合 "xxx aaa xxx" 時,匹配結果是:失敗。因為 "^" 要求與字串開始的地方匹配,因此,只有當 "aaa" 位於字串的開頭的時候,"^aaa" 才能匹配,例如:"aaa xxx xxx"。
範例2:表達式 "aaa$" 在符合 "xxx aaa xxx" 時,匹配結果是:失敗。因為 "$" 要求與字串結束的地方匹配,因此,只有當 "aaa" 位於字串的結尾的時候,"aaa$" 才能匹配,例如:"xxx xxx aaa"。
範例3:表達式"./b." 在匹配"@@@abc" 時,匹配結果是:成功;匹配到的內容是:"@a";匹配到的位置是:開始於2,結束於4。
進一步說明:"/b" 與"^" 和"$" 類似,本身不匹配任何字符,但是它要求它在匹配結果中所處位置的左右兩邊,其中一邊是"/w" 範圍,另一邊是非"/w" 的範圍。
範例4:表達式"/bend/b" 在匹配"weekend,endfor,end" 時,匹配結果是:成功;匹配到的內容是:"end";匹配到的位置是:開始於15,結束於18。
一些符號可以影響表達式內部的子表達式之間的關係:
表達式 | 作用 |
#| | |
左右兩邊表達式之間"或" 關係,匹配左邊或右邊 |
(2). 取匹配結果的時候,括號中的表達式匹配到的內容可以被單獨得到
#舉例5:表達式"Tom|Jack " 在匹配字串"I'm Tom, he is Jack" 時,匹配結果是:成功;匹配到的內容是:"Tom";匹配到的位置是:開始於4,結束於7。匹配下一個時,匹配結果是:成功;匹配到的內容是:"Jack";匹配到的位置時:開始於15,結束於19。 範例6:表達式"(go/s*) " 在匹配"Let's go go go!" 時,匹配結果是:成功;匹配到內容是:"go go go";匹配到的位置是:開始於6,結束於14。
範例7:表達式"¥(/d /.?/d*)" 在配對"$10.9,¥20.5" 時,配對的結果是:成功;符合的內容是:"¥ 20.5";配對到的位置是:開始於6,結束於10。單獨取得括號範圍所符合的內容是:"20.5"。
2. 正規表示式中的一些高階規則
#2.1 符合次數中的貪婪與非貪婪 | 在使用修飾匹配次數的特殊符號時,有幾種表示方法可以使同一個表達式能夠匹配不同的次數,例如:"{m,n}", "{m,}", " ?", "*", " ",具體符合的次數隨被符合的字串而定。這種重複匹配不定次數的表達式在匹配過程中,總是盡可能多的匹配。例如,針對文字"dxxxdxxxd",舉例如下:|
符合結果 | |
"/w " 將符合第一個"d" 之後的所有字元"xxxdxxxd " |
由此可見,"/w " 在匹配的時候,總是盡可能多的匹配符合它規則的字元。雖然第二個舉例中,它沒有符合最後一個 "d",但那也是為了讓整個表達式能夠匹配成功。同理,帶有 "*" 和 "{m,n}" 的表達式都是盡可能地多匹配,帶 "?" 的表達式在可匹配可不匹配的時候,也是盡可能的 "要匹配"。這 種配對原則就叫作 "貪婪" 模式 。
非貪婪模式:
在修飾符合次數的特殊符號後再加上一個"?" 號,則可以使符合次數不定的表達式盡可能少的匹配,使可匹配可不匹配的表達式,盡可能的"不匹配"。這種匹配原則叫作 "非貪婪" 模式,也叫作 "勉強" 模式。如果少匹配就會導致整個表達式匹配失敗的時候,與貪婪模式類似,非貪婪模式會最小限度的再匹配一些,以使整個表達式匹配成功。舉例如下,針對文字"dxxxdxxxd" 舉例:
#表達式 | 比 |
更多的情況,舉例如下:
舉例1:表達式"
aa< ;/p>
bb
bb
舉例2:相較之下,表達式"
aa
bb
2.2 反向引用/1, /2...
表達式在符合時,表達式引擎會將小括號"( )" 包含的表達式式所匹配到的字串記錄下來。在取得符合結果的時候,小括號包含的表達式所符合的字串可以單獨取得。這一點,在前面的舉例中,已經多次展示了。在實際應用場合中,當用某種邊界來查找,而所要取得的內容又不包含邊界時,必須使用小括號來指定所要的範圍。例如前面的 "
其實,"小括號包含的表達式所匹配到的字串" 不僅是在匹配結束後才可以使用,在匹配過程中也可以使用。表達式後邊的部分,可以引用前面 "括號內的子符合已經符合的字串"。引用方法是 "/" 加上一個數字。 "/1" 引用第1對括號內匹配到的字串,"/2" 引用第2對括號內匹配到的字串…以此類推,如果一對括號內包含另一對括號,則外層的括號先排序號。換句話說,哪一對的左括號"(" 在前,那這一對就先排序號。
舉例如下:
舉例1:表達式"('|" )(.*?)(/1)" 在匹配" 'Hello', "World" " 時,匹配結果是:成功;匹配到的內容是:" 'Hello' "。再次匹配下一個時,可以匹配到" "World" "。
範例2:表達式"(/w)/1{4,}" 在匹配"aa bbbb abcdefg ccccc 111121111 999999999" 時,匹配結果是:成功;匹配到的內容是"ccccc"。再次符合下一個時,將得到999999999。這個表達式要求"/w" 範圍的字元至少重複5次,注意與"/w{5,}" 之間的區別。
範例3:表達式"<(/w )/s*(/w (=('|").*?/4)?/s*)*>.*?/ 1>" 在匹配"
2.3 預搜索,不匹配;反向預搜索,不匹配
前面的章節中,我講到了幾個代表抽象意義的特殊符號:"^","$","/b"。它們都有一個共同點,那就是:它們本身不匹配任何字符,只是對"字串的兩頭" 或"字元之間的縫隙" 附加了一個條件。理解到這個概念以後,本節將繼續介紹另外一種對"兩頭" 或"縫隙" 附加條件的,更加靈活的表示方法。
正向預先搜尋:"(?=xxxxx)","(?!xxxxx)"
格式:"(?=xxxxx)",在已符合的字串中,它對所處的"縫隙" 或"兩頭" 附加的條件是:所在縫隙的右側,必須能夠匹配上xxxxx 這部分的表達式。因為它只是在此作為這個縫隙上附加的條件,所以它不會影響後邊的表達式去真正匹配這個縫隙之後的字符。這就類似"/b",本身不匹配任何字符。"/b" 只是將所在縫隙之前、之後的字符取來進行了一下判斷,不會影響後邊的表達式來真正的匹配。
舉例1:表達式"Windows (?=NT|XP)" 在匹配"Windows 98, Windows NT, Windows 2000" 時,將只符合"Windows NT" 中的"Windows ",其他的"Windows " 字樣則不被符合。
範例2:表達式"(/w)((?=/1/1/1)(/1)) " 在符合字串"aaa ffffff 999999999" 時,將可以符合6個"f"的前4個,可以搭配9個"9"的前7個。這個表達式可以讀解成:重複4次以上的字母數字,則符合其剩下最後2位元之前的部分。當然,這個表達式可以不這樣寫,在此的目的是作為演示之用。
格式:"(?!xxxxx)",所在縫隙的右側,必須不能符合 xxxxx 這部分錶達式。
範例3:表達式"((?!/bstop/b).) " 在匹配"fdjka ljfdl stop fjdsla fdj" 時,將從頭一直匹配到"stop" 之前的位置,如果字串中沒有"stop",則符合整個字串。
範例4:表達式 "do(?!/w)" 在符合字串 "done, do, dog" 時,只能符合 "do"。在本條舉例中,"do" 後邊使用 "(?!/w)" 和使用 "/b" 效果是一樣的。
反向預先搜尋:"(?<=xxxxx)","(?
這兩種格式的概念和正向預搜尋是類似的,反向預搜尋要求的條件是:所在縫隙的"左側",兩種格式分別要求必須能夠匹配和必須不能夠匹配指定表達式,而不是去判斷右側。與 "正向預搜尋" 一樣的是:它們都是對所在縫隙的一種附加條件,本身都不符合任何字元。
範例5:表達式"(?<=/d{4})/d (?=/d{4})" 在符合"1234567890123456" 時,將符合除了前4個數字和後4個數字之外的中間8個數字。由於 JScript.RegExp 不支援反向預搜索,因此,本條舉例無法進行示範。許多其他的引擎可以支援反向預搜索,例如:Java 1.4 以上的 java.util.regex 包,.NET 中System.Text.RegularExpressions 命名空間,以及本站推薦的最簡單易用的 DEELX 正則引擎。
3. 其他通用規則
還有一些在各個正規表示式引擎之間比較通用的規則,在前面的講解過程中沒有提到。
3.1 表達式中,可以使用"/xXX" 和"/uXXXX" 表示一個字元("X" 表示一個十六進位數)
形式 | 字元範圍 |
/xXX | #編號在0 ~ 255 範圍的字符,例如:空格可以使用"/x20" 表示 |
/uXXXX | 任何字元可以使用"/u" 再加上其編號的4位十六進位數表示,例如:"/中" |
#3.2 在表達式"/s","/d","/w","/b" 表示特殊意義的同時,對應的大寫字母表示相反的意義
表達式 | #可符合 |
/S | 符合所有非空白字元("/s" 可符合各個空白字元) |
/D | 符合所有的非數字字元 |
/W | 符合所有的字母、數字、底線以外的字元 |
/B | #符合非單字邊界,即左右兩邊都是"/w"範圍或左右兩邊都不是"/w" 範圍時的字元縫隙 |
3.3 在表達式中有特殊意義,需要添加"/" 才能匹配該字元本身的字元匯總
字元 | 說明 |
^ | #符合輸入字串的開始位置。要匹配"^" 字元本身,請使用"/^" |
#$ | ##來匹配輸入字串的結尾位置。要匹配"$" 字元本身,請使用"/$" |
#( ) | 標記一個子表達式的開始和結束位置。要符合小括號,請使用"/(" 和"/)" |
#[ ] | 來自定義能夠匹配'多種字元' 的表達式。若要匹配中括號,請使用"/[" 和"/]" |
#{ } | 修飾匹配次數的符號。若要符合大括號,請使用"/{" 和"/}" |
#. | 「換行符(/n)以外的任一個字元。要符合小數點本身,請使用"/." |
#? | ## 修飾符合次數為0 次或1次。若要符合"?" 字元本身,請使用"/?"|
修飾符合次數為至少1次。要匹配" " 字元本身,請使用"/ " | |
修飾匹配次數為0 次或任意次。要符合"*" 字元本身,請使用"/*" | |
左右兩邊表達式之間"或" 關係。匹配"|" 本身,請使用"/|" |
舉例1:表達式"(?:(/w)/1) " 匹配"a bbccdd efg" 時,結果是"bbccdd"。括號 "(?:)" 範圍的符合結果不進行記錄,因此 "(/w)" 使用 "/1" 來引用。
3.5 常用的表達式屬性設定簡介:Ignorecase,Singleline,Multiline,Global##說明 | |
預設情況下,表達式中的字母是要區分大小寫的。配置為 Ignorecase 可使匹配時不區分大小寫。有的表達式引擎,把 "大小寫" 概念延伸到 UNICODE 範圍的大小寫。 | |
#預設情況下,小數點"." 符合除了換行符號(/n)以外的字符。配置為 Singleline 可使小數點可符合包括換行符號在內的所有字元。 | |
#預設情況下,表達式"^" 和"$" 只符合字串的開始① 和結尾④ 位置。如: |
①xxxxxxxxx②/n |
#主要在將表達式用來替換時起作用,配置為Global 表示取代所有的匹配。 |