官术网_书友最值得收藏!

7.2 正則表達式語法

正則表達式的語法主要就是對各個元字符功能的描述。元字符從功能上大致分為模式匹配符、定位符與原義字符、限定符、選擇匹配符、特殊字符、字符匹配符、分組組合和反向引用符。本節將對各種元字符進行詳細講解。

7.2.1 模式匹配符

表7.1列出了在正則表達式中能夠使用的字符列表及相關描述。

表7.1 模式匹配符

續表

7.2.2 定位符與原義字符

在進行數據驗證時,可以使用一些定位符來限定字符出現的位置,以方便匹配。同時,對于表達式中的元字符,需要進行轉義,使其變成原義字符,才能正常顯示出來。下面詳細介紹這兩種字符。

(1)文本驗證定位符

定位符用于規定匹配模式在目標字符串中出現的位置,例如,規定匹配模式只能出現在開頭或結尾處,這樣對文本格式的驗證非常有用。

在正則表達式中,有以下幾個用于驗證文本的定位符。

用“^”匹配目標字符串的開始位置

匹配必須發生在目標字符串的開頭處,“^”必須出現在表達式的最前面,才具有定位符作用。

例如,“^o”與“ok”中的“o”匹配,但與“no”中的“o”不匹配。如果設置了RegExp對象實例的multiline屬性,“^”還會與行首匹配,即與“\n”或“\r”之后的位置匹配。

【例7.1】 匹配字符“^”的使用。(實例位置:資源包\TM\sl\7\01)

運行程序,在瀏覽器窗口中會顯示匹配成功的相關內容,如圖7.1所示。

圖7.1 匹配字符“^”的使用

代碼如下:

用“$”匹配目標字符串的結尾位置

匹配必須發生在目標字符串的結尾處,“$”必須出現在表達式的最后面,才具有定位符作用。

例如,“o$”與“no”中的“o”匹配,但與“ok”中的“o”不匹配。如果設置了RegExp對象實例的mutiline屬性,“$”還會與行末匹配,即與“\n”“\r”之前的位置匹配。

【例7.2】 匹配字符“$”的使用。(實例位置:資源包\TM\sl\7\02)

運行程序,在瀏覽器窗口中會顯示匹配成功的相關內容,如圖7.2所示。

圖7.2 匹配字符“$”的使用

代碼如下:

用“\b”匹配一個字邊界

“\b”包含了字符與空格間的位置,以及目標字符串的開始和結束位置等。

例如,“er\b”匹配“order to”中的“er”,但不匹配“verb”中的“er”。

【例7.3】 匹配字符“\b”的使用。(實例位置:資源包\TM\sl\7\03)

運行程序,在瀏覽器窗口中會顯示匹配成功的相關內容,如圖7.3所示。

圖7.3 匹配字符“\b”的使用

代碼如下:

用“\B”匹配非字邊界

例如,“er\B”匹配“verb”中的“er”,但不匹配“order”中的“er”。

(2)特殊字符轉義

在表達式中用到的一些元字符不再表示原來的字面意義。如果要匹配這些有特殊意義的元字符,必須使用“\”將這些字符轉義為原義字符。需要進行轉義的字符有“$”“(”“)”“*”“+”“.”“[”“]”“?”“\”“/”“^”“{”“}”和“|”。

“\”的作用是將下一字符標記為特殊字符、原義字符、反向引用或八進制轉義符,所以,要匹配字面意義的“\”,需要使用“\\”表示。

7.2.3 限定符與選擇匹配符

(1)限定符

用“+”限定必須出現一次或連續多次

“+”元字符規定其前導字符必須在目標對象中出現一次或連續多次。

如“/fo+/”,因為上述正則表達式中包含“+”元字符,表示可以與目標對象中的“fool”、“fo”或者“football”等在字母“f”后面連續出現一個或多個字母“o”的字符串相匹配,但與一個單獨的“f”不匹配。“+”等效于“{1,}”。

用“*”限定可以出現的次數

“*”元字符規定其前導字符必須在目標對象中出現零次或連續多次。

如“/eg*/”,因為上述正則表達式中包含“*”元字符,表示可以與目標對象中的“easy”、“ego”或者“egg”等在字母“e”后面連續出現0個或多個字母“g”的字符串相匹配。“*”等效于“{0,}”。

用“?”限定最多出現一次

“?”元字符規定其前導字符必須在目標對象中出現0次或1次。

如“/Wil?/”,因為上述正則表達式中包含“?”元字符,表示可以與目標對象中的“Win”或者“Wilson”等在字母“i”后面連續出現0個或1個字母“l”的字符串相匹配,但不能匹配“Will”。“?”等效于“{0,1}”。

用“{n}”限定連續出現的次數

規定前面的元素或組合項連續出現n次。n為非負整數。

例如,“o{2}”不能與“job”中的“o”匹配,但可以與“book”中的兩個“o”匹配,也可以與“booook”中的任意兩個連續的“o”匹配。

用“{n,}”限定至少出現的次數

規定前面的元素或組合項至少連續出現n次。n為非負整數。

例如,“o{2,}”不能與“job”中的“o”匹配,但可以與“booook”中的所有“o”匹配。

用“{n,m}”限定最少與最多出現的次數

規定前面的元素或組合項至少連續出現n次,最多連續出現m次。m和n是非負整數,其中n≤m,逗號和數字之間不能有空格。

例如,“o{1,3}”既可匹配“book”中的兩個“o”,又可匹配“booook”中3個連續的“o”。

(2)貪婪匹配與非貪婪匹配

默認情況下,正則表達式使用最長匹配原則,即貪婪匹配原則。

例如,要將“book”中匹配“bo?”的部分替換成“l”,替換后的結果是“lok”,而不是“look”;如果要將“book”中匹配“bo*”的部分替換成“l”,替換后的結果是“lk”,而不是“lok”或“look”。

當解釋器將代碼中的字符解析成一個個的編譯器,并在處理代碼當前最小語法單元時,編譯器會使用一種貪婪匹配算法。也就是說,會盡可能讓一個單元包含更多的字符。如果當字符“?”緊跟任何其他限定符(“*”“+”“?”“{n}”“{n,}”“{n,m}”)之后時,匹配模式變成使用最短匹配原則,即非貪婪匹配原則。例如,在字符串“booook”中,“bo+?”只匹配“bo”部分,而“bo+”匹配“boooo”部分。

(3)選擇匹配符

選擇匹配符“|”,用于選擇匹配兩個選項之中的任意一個,其兩個選項是“|”字符兩邊盡可能最大的表達式。

例如,“abcd|efgh1”匹配的是“abcd”或“efgh”,而不是“abcd1”或“efgh1”;如果要匹配“abcd1”或“efgh1”,應該使用括號創建子表達式,即“(abcd|efgh) 1”。

7.2.4 字符匹配符

字符匹配符用于指定可以匹配多個字符中的任意一個。

“[…]”匹配方括號中包含的字符集中的任意一個字符。

例如,“[abc]”可以與“a”“b”“c”3個字符中的任何一個匹配。如果字符集中要包含“]”字符,需將其放在第一位,即緊跟在“[”后面。“[]”中的字符“\”仍作為轉義字符,若要在“[…]”中包含“\”字符本身,需使用“\\”。

“[^…]”匹配方括號中未包含的任意字符。

例如,“[^abc]”可匹配“a”“b”“c”3個字符之外的任何字符。只要字符“^”不是出現在第一個“[”后面,就還是字面意義上的“^”。

“[a-z]”匹配指定范圍內的任何字符。

例如,“[1-9]”匹配1~9的任何數字字符。若要在方括號中包含字面意義的連字符“-”,可以用“\”將其標記為原義字符,例如“[a\-z]”。也可以將“-”放在方括號的開始或結尾處,例如,“[-a-z]”或“[a-z-]”匹配所有小寫字母和連字符。

“[^a-z]”匹配不在指定范圍內的任何字符。

例如,“[^a-z]”匹配不在a~z之間的任何字符。

【例7.4】 字符匹配的使用。(實例位置:資源包\TM\sl\7\04)

運行程序,在瀏覽器窗口中會顯示匹配成功的相關內容,如圖7.4所示。

圖7.4 字符匹配

代碼如下:

“\w”匹配任何單字字符,即英文字母或者數字類字符以及下畫線,等效于“[A-Za-z0-9_]”。

“\W”匹配任何非單字字符,即非英文字母或者數字類字符,但不包括下畫線。“\W”是“\w”的逆運算,等效于“[^A-Za-z0-9_]”。

“\s”匹配任何空白字符,包括空格、制表符、回車符、換行符等,等效于“[\f\n\r\t\v]”。

“\S”匹配任何非空白字符,是“\s”的逆運算,等效于“[^\f\n\r\t\v]”。

“\d”匹配任何一個數字字符,等效于“[0-9]”。

“\D”匹配任何一個非數字字符,是“\d”的逆運算,等效于“[^0-9]”。

“.”匹配除“\n”之外的任何單個字符。

“()”標記一個子表達式的開始和結束位置。子表達式可以獲取供以后使用。要匹配這些字符,請使用“\(”和“\)”。

“(.)\l”匹配除“\n”之外的兩個連續的相同字符。若要匹配包括“\n”在內的任意字符,可以使用“[\s\S]”、“[\d\D]”或“[\w\W]”等模式。若要匹配“.”字符本身,需要使用“\.”。

【例7.5】 圓點(.)元字符的使用。(實例位置:資源包\TM\sl\7\05)

運行結果如圖7.5所示。

圖7.5 圓點(.)元字符的使用

代碼如下:

7.2.5 分組組合與反向引用符

分組組合符是將表達式中某部分內容組合起來的符號,反向引用符則是用于匹配分組組合捕獲到的內容的標識符。

(1)分組組合

“(pattern)”將pattern部分組合成一個可統一操作的組合項和子匹配,每個捕獲的子匹配項按照出現的順序存儲在緩沖區中。緩沖區編號從1開始,最多可存儲99個子匹配捕獲的內容。存儲在緩沖區中的子匹配捕獲的內容,可以在編程語言中被檢索,也可以在正則表達式中被反向引用。若要匹配字面意義的括號字符“(”和“)”,在正則表達式中要分別使用“\(”和“\)”。

(2)反向引用

“\num”匹配編號為num的緩沖區所保存的內容,num是標識特定緩沖區的一位或兩位十進制正整數,這種方式稱為子匹配的反向引用。反向引用能提供表示相同匹配項的能力。

(3)非捕獲匹配

“(?:pattern)”匹配pattern但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。它是將pattern部分組合成一個可統一操作的組合項,但不把這部分內容當作子匹配捕獲,即pattern部分是一個非捕獲匹配,匹配的內容不存儲在緩沖區中供以后使用。這對必須進行組合,但又不想讓組合的部分具有子匹配特點的情況很有用。

例如,要將“abc?”中的“abc”組合起來,但并不想將匹配的內容保存在緩沖區中,應該使用“(?:abc)?”,而不能使用“(abc)?”。又如,不能將“industry|industries”簡單改寫為“industry(ylies)”,若不需要引用或檢索括號中的表達式所匹配的結果,最好還是寫成“industry(?:ylies)”。

(4)正向“預測先行”匹配

“(?=pattern)”稱為正向“預測先行”匹配,在任何匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。在被搜索字符串的相應位置必須有pattern部分匹配的內容,但不作為匹配結果處理,更不會存儲在捕獲緩沖區中供以后使用。

例如,“Windows (?=NT|2000)”只與“Windows 2000”或“Windows NT”中的“Windows”匹配,而不與“Windows 2003”中的“Windows”匹配。

注意

該模式下匹配的結果只是“Windows”部分,而使用“Windows (?:NT|2000)”匹配的是整個“Windows 2000”或“Windows NT”。如果要將“NT”和“2000”前面的“Windows”替換成“Win”,需要使用“Windows (?=NT|2000)”,而不能使用“Windows (?:NT|2000)”;否則,整個“Windows 2000”或“Windows NT”將被替換成“Win”。

(5)反向“預測先行”匹配

“(?!pattern)”稱為反向“預測先行”匹配,在被搜索字符串的相應位置不能有pattern部分匹配的內容,此外,其功能與正向“預測先行”匹配一樣。

例如,“Windows (?!NT|2000)”不與“Windows 2000”或“Windows NT”中的“Windows”匹配,但可以與“Windows 2003”中的“Windows”匹配。

7.2.6 實際應用

正則表達式主要用于字符串處理、表單驗證等。下面介紹一些常用的正則表達式。

(1)普通字符匹配

下面是一些在Web編程中經常會遇到的字符匹配模式。

匹配中文字符的正則表達式。

    [\u4e00-\u9fa5]

匹配雙字節字符(包括漢字在內)的正則表達式。

    [^x00-xff]

匹配空行的正則表達式。

    n[s|]*r

匹配HTML標記的正則表達式。

    /<(.*)>.*</1>|<(.*) />/

匹配首尾空格的正則表達式。

    (^s*)|(s*$)

計算字符串長度(一個雙字節字符長度計2,ASCII字符計1)的正則表達式。

    String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;}

匹配網址URL的正則表達式。

    http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?

匹配E-mail地址的正則表達式。

    w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*

(2)限制表單所輸入的內容

有時需要限制網頁表單文本框中輸入的內容。下面是一些利用正則表達式來實現這種功能的實例。

用正則表達式限制只能輸入中文。

    onkeyup="value=value.replace(/[^u4E00-u9FA5]/g,'')"
    onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))"

用正則表達式限制只能輸入數字。

    onkeyup="value=value.replace(/[^d]/g,'')
    "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"

用正則表達式限制只能輸入數字和英文。

    onkeyup="value=value.replace(/[W]/g,'')
    "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"

用正則表達式限制只能輸入全角字符。

    onkeyup="value=value.replace(/[^uFF00-uFFFF]/g,'')"
    onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))"

(3)去掉重復的字符

利用正則表達式可以去掉字符串中重復的字符。

例如,下面的例子利用正則表達式去掉了字符串中重復的字符。首先應用正則表達式取出重復的字符,再以重復的字符建立第二個表達式,取到不重復的字符,最后兩者串聯,代碼如下:

    var s="abacabefgeeii"
    var s1=s.replace(/(.).*\1/g,"$1")
    var re=new RegExp("["+s1+"]","g")
    var s2=s.replace(re,"")
    alert(s1+s2);

運行結果:

    abeicfg

說明

這種方法對于字符順序有要求的字符串可能不適用。

主站蜘蛛池模板: 龙胜| 龙井市| 资兴市| 信阳市| 红原县| 久治县| 枣强县| 博爱县| 霞浦县| 马边| 嘉善县| 和平县| 潜山县| 高碑店市| 肇源县| 东方市| 克拉玛依市| 石楼县| 普安县| 武城县| 搜索| 弥勒县| 清河县| 兴仁县| 舒兰市| 沅江市| 垣曲县| 梁河县| 张北县| 广安市| 旬阳县| 舞阳县| 陕西省| 乌拉特中旗| 横山县| 临安市| 阆中市| 蒙自县| 古交市| 成武县| 钦州市|