寶貝小豬嘜

          常用鏈接

          統計

          最新評論

          正則表達式

          1.什么是正則表達式


          簡單的說,正則表達式是一種可以用于文字模式匹配和替換的強有力的工具。是由一系列普通字符和特殊字符組成的能明確描述文本字符串的文字匹配模式。

          正則表達式并非一門專用語言,但也可以看作是一種語言,它可以讓用戶通過使用一系列普通字符和特殊字符構建能明確描述文本字符串的匹配模式。除了簡單描述這些模式之外,正則表達式解釋引擎通常可用于遍歷匹配,并使用模式作為分隔符來將字符串解析為子字符串,或以智能方式替換文本或重新設置文本格式。正則表達式為解決與文本處理有關的許多常見任務提供了有效而簡捷的方式。

          正則表達式具有兩種標準:

          · ? ? ? 基本的正則表達式(BRE – Basic Regular Expressions)

          · ? ? ? 擴展的正則表達式(ERE – Extended Regular Expressions)。

          ERE包括BRE功能和另外其它的概念。



          正則表達式目前有兩種解釋引擎:

          · ? ? ? 基于字符驅動(text-directed engine)

          · ? ? ? 基于正則表達式驅動(regex-directed engine)

          Jeffery Friedl把它們稱作DFA和NFA解釋引擎。



          約定:

          為了描述起來方便,在本文中做一些約定:

          1. ? ? 本文所舉例的所有表達時都是基于NFA解釋引擎的。

          2. ? ? 正則表達式,也就是匹配模式,會簡寫為Regex。

          3. ? ? Regex的匹配目標,也就是目標字符串,會簡寫為String。

          4. ? ? 匹配結果用會用黃色底色標識。

          5. ? ? 用1\+1=2 括起來的表示這是一個regex。

          6. ? ? 舉例會用以下格式:
          test
          This is a test
          會匹配test,testcase等


          2.正則表達式的起源
          正則表達式的“祖先”可以一直上溯至對人類神經系統如何工作的早期研究。Warren McCulloch 和 Walter Pitts 這兩位神經生理學家研究出一種數學方式來描述這些神經網絡。

          1956 年, 一位叫 Stephen Kleene 的美國數學家在 McCulloch 和 Pitts 早期工作的基礎上,發表了一篇標題為“神經網事件的表示法”的論文,引入了正則表達式的概念。正則表達式就是用來描述他稱為“正則集的代數”的表達式,因此采用“正則表達式”這個術語。

          隨后,發現可以將這一工作應用于使用Ken Thompson 的計算搜索算法的一些早期研究,Ken Thompson是Unix 的主要發明人。正則表達式的第一個實用應用程序就是 Unix 中的qed 編輯器。從那時起直至現在正則表達式都是基于文本的編輯器和搜索工具中的一個重要部分。具有完整語法的正則表達式使用在字符的格式匹配方面上,后來被應用到熔融信息技術領域。自從那時起,正則表達式經過幾個時期的發展,現在的標準已經被ISO(國際標準組織)批準和被Open Group組織認定。

          3. 正則表達式使用祥解
          最簡單的正則表達式相信大家都已熟悉并且經常使用,那就是文字字符串。特定的字符串可通過文字本身加以描述;像 test這樣的Regex模式可精確匹配輸入的字符串”test”,但是它也可以匹配this is a testcase,這就不是我們想要得結果。

          當然,使用正則表達式匹配等于它自身的精確字符串是沒有價值的實現,不能體現正則表達式的真正作用。但是,假如要查找的不是test,而是所有以字母 t 開頭的單詞,或所有4個字母的單詞,那該怎么辦?這超出了文字字符串的合理范圍。所以我們才需要深入地研究正則表達式。

          3.1基本語法
          雖然正則表達式并非一門專用語言,但它也有一些特殊的規定,也可以稱之為基本語法。

          正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式。該模式描述在查找文字主體時待匹配的一個或多個字符串。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。

          構造正則表達式的方法和創建數學表達式的方法一樣。也就是用多種元字符與操作符將小的表達式結合在一起來創建更大的表達式。

          可以通過在一對分隔符之間放入表達式模式的各種組件來構造一個正則表達式。

          3.1.1普通字符
          由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫和小寫字母字符,所有數字,所有標點符號以及一些符號。

          3.1.2非打印字符
          非打印字符也是普通字符,單獨列出來便于參考。

          非打印字符參考
          \cx
          匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。

          \f
          匹配一個換頁符。等價于 \x0c 和 \cL。

          \n
          匹配一個換行符。等價于 \x0a 和 \cJ。

          \r
          匹配一個回車符。等價于 \x0d 和 \cM。

          \s
          匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。

          \S
          匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。

          \t
          匹配一個制表符。等價于 \x09 和 \cI。

          \v
          匹配一個垂直制表符。等價于 \x0b 和 \cK。

          Regex中可以使用非打印字符。\t會匹配一個tab字符(ASC||),\r 會匹配一個回車(0x0D),\n 會匹配一個換行符(0x0A)。應該注意的是:Windows使用\r\n表示一行的結束,而UNIX使用\n 。

          同樣,我們可以在Regex中使用16進制的ASCⅡ碼或者ANSI標準碼。在拉丁語中,版權符號的代碼是0xA9,所以我們也可以這樣來匹配版權符號 \xA9 。另外一個匹配tab的寫法是:\x09 。但是注意,第一位的“0”必須去掉。


          特殊字符
          特殊字符也叫做元字符,保留字符(Metacharactor),在Regex中表示特殊的意義,大部分的意思在不同的上下文中的意義是不同的,這里只列出最普遍的意義。

          特殊字符共有11個:
          $
          匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請使用 \$。

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

          *
          匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*。

          +
          匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+。

          .
          匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \。

          [
          標記一個中括號表達式的開始。要匹配 [,請使用 \[。

          ?
          匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。

          \
          將下一個字符標記為或特殊字符、或原義字符、或反向引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。

          ^
          匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^。

          {
          標記限定符表達式的開始。要匹配 {,請使用 \{。

          |
          指明兩項之間的一個選擇。要匹配 |,請使用 \|。

          在元字符前加 \ 轉義符,可以把特殊字符當作普通字符來使用。

          比如:如要要匹配 1+1=2 ,正確的正則表達式應該為1\+1=2。否則, + 會被當作特殊字符對待。

          除了特殊字符,所有的其他字符都不應該加 \ 。因為 \ 也是一個特殊字符。\ 和普通字符組合在一起也可以創造一種特殊的意義。比如 \d 表示匹配所有的數字。

          作為程序員,單引號和雙引號不是特殊字符會也許讓我們感到很驚訝。但這是正確的。因為我們在編程的時候,編程語言會知道引號之間的哪些字符表示特殊意義,編譯器在把字符串x傳遞給regex解釋引擎之前,會把它們處理成regex。比如,在C#中,如果我們要匹配 1\+1=2 ,在程序中我們要這樣寫: “1\\+1=2” ,C#編譯器會把 “\\” ,處理為一個“\” 。同樣,如果要匹配 C:\Temp ,首先,正則表達式要這樣寫 C:\\Temp,然后在程序中我們應該這樣寫:“ C:\\\\temp”。

          3.1.4字符集
          ? ? ? ? 字符集描述了一組字符,Regex解釋器會認為匹配字符集中的一個字符就可以認為匹配成功。

          字符集用[ ]括起來即可。

          ? ? ? ? 比如gr[ae]y就可以匹配gray或者grey。

          ? ? ? ? 字符集只能匹配一個字符,gr[ae]y就不能和graey匹配。字符集中的字符順序是任意的,得到的結果都是唯一的。

          ? ? ? ? 可以在字符集中用連字符“-”來表示一個范圍。[0-9]的結果和[0123456789]的匹配結果都是相同的。字符集中的范圍可以有多種。比如[0-9a-fA-F]表示匹配所有的16進制,包括大小寫。也可以把范圍和單個字符組合在一起用,[0-9a-fxA-FX]表示匹配所有的16進制或者一個字符X。字符集的順序不會影響結果。

          ? ? ? ? 在字符集的開始標志“[”后面加上一個“^”符號,表示否定,表示匹配除字符集中定義的字符以外的所有字符。包括非打印字符和行結束符。

          ? ? ? ? 注意:字符集匹配的一個字符,而不是一個位置。所以。q[^u]的意義不是“q后面的字符不是u”。而是“q后面的字符可以是除了u以外的所有字符”。

          ? ? ? ? q[^u]不會和Iraq匹配。

          但是會和Iraq is a country匹配,因為q后面的空格字符是一個“不是u的字符”。

          3.1.5在字符集中使用元字符
          字符集中的元字符只能是 ‘]’, ‘\’, ‘^’, 和 ‘-‘ 。

          其他元字符在字符集中都失去了特殊意義,表示的只是一個普通字符。也不需要用加“\”。

          比如:

          匹配一個“*”或者“+”,用[*+]就足夠了。即使給他們加上“\”,regex解釋器也會把他們忽略掉。



          四種特殊字符的處理:

          在字符集中要表示“]”,“^”和“-”需要在后面加上轉義符“\”,來表示它們代表的分別是普通字符“]”,“^”和“-”。

          也可以把它們放在一個不能表示特殊意義的位置,后一個方法比較好,因為他們不會影響可讀性。

          “^”
          要想匹配一個“^”,可以把它放在除了緊跟“[”的任意一個位置。

          Regex
          String
          Description

          [x^]
          A string with x and ^.
          匹配x或者“^”




          “]”
          可以把“]”放在緊跟著“[”的位置,或者使用否定字符集。

          Regex
          String
          Description

          []x]
          A string with x and ]
          匹配x或者“]”

          [^]x]
          A string with x and ]
          匹配除了x和”] ”以外的所有字符


          “\”
          要想把“\”當作一個普通字符來匹配,而不是一個特殊字符,必須把“\”再用一個“\”括起來。


          [\\x]
          A string with x and \
          匹配x或者“\”




          “-”
          連字符可以放在緊跟著“[”的后面,或者正好“]”的前面,或者緊跟著“^”的后面。



          [-x]
          A string with x and -
          匹配x或者“-”

          [x-]
          A string with x and -
          匹配x或者“-”

          預定義字符集
          因為很多字符集是經常使用的,所以Regex解釋器預定義了一些常用字符集:

          d
          [0-9]
          所有數字

          \w
          [a-zA-Z0-9]
          表示所有的字符,和文化字體有關

          \s
          [ \t\r\n]

          空格,回車和tab。和文化字體有關

          預訂一字符集可以既可以用在字符集里面,也可以用在字符集外面。
          \s\d
          1<space>+<space>2<space>=<space>3
          匹配后面緊跟著一個數字的空白符

          [\s\d]
          1<space>+<space>2<space>=<space>3
          匹配一個單獨的字符或者一個數字或者一個空白符

          [\da-fA-F]和[0-9a-fA-F]的匹配結果是一樣的。



          同樣,在預定義字符集前面加一個“^”符號表示否定。它們也有預先定義好的表示:

          \D
          [^\d]
          非數字

          \W
          [^\w]
          非字符,和文化字體有關

          \S
          [^\s]
          非空格,回車和tab。和文化字體有關

          在“[]”使用否定預訂一字符集時要特別心。[\D\S]不等于[^\d\s]。[^\d\s]會匹配除了數字和空白符以外的所有字符。而[\D\S]會匹配要么不是一個數字,要么是空白符。因為數字不是空白符,空白符也不是數字,所以[\D\S]會匹配任意的字符。
          限定符
          有時候不知道要匹配多少字符。為了能適應這種不確定性,正則表達式支持限定符的概念。這些限定符可以指定正則表達式的一個給定組件必須要出現多少次才能滿足匹配。

          下表給出了各種限定符及其含義的說明:

          * 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等價于{0,}。
          + 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價于 {1,}。
          ? 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價于 {0,1}。
          {n} n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
          {n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價于 'o+'。'o{0,}' 則等價于 'o*'。
          {n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。劉, "o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價于 'o?'。請注意在逗號和兩個數之間不能有空格。
          對一個很大的輸入文檔而言,章節數很輕易就超過九章,因此需要有一種方法來處理兩位數或者三位數的章節號。限定符就提供了這個功能。下面的JScript 正則表達式可以匹配具有任何位數的章節標題:

          /Chapter [1-9][0-9]*/
          下面的 VBScript 正則表達式執行同樣的匹配:

          "Chapter [1-9][0-9]*"
          請注意限定符出現在范圍表達式之后。因此,它將應用于所包含的整個范圍表達式,在本例中,只指定了從 0 到 9 的數字。

          這里沒有使用 '+' 限定符,因為第二位或后續位置上并不一定需要一個數字。同樣也沒有使用 '?' 字符,因為這將把章節數限制為只有兩位數字。在 'Chapter' 和空格字符之后至少要匹配一個數字。

          如果已知章節數限制只有99 章,則可以使用下面的 JScript 表達式來指定至少有一位數字,但不超過兩個數字。

          /Chapter [0-9]{1,2}/
          對 VBScript 可以使用下述正則表達式:

          "Chapter [0-9]{1,2}"
          上述表達式的缺點是如果有一個章節號大于 99,它仍只會匹配前兩位數字。另一個缺點是某些人可以創建一個 Chapter 0,而且仍能匹配。一個更好的用來匹配兩位數的 JScript 表達式如下:

          /Chapter [1-9][0-9]?/
          或者

          /Chapter [1-9][0-9]{0,1}/
          對 VBScript 而言,下述表達式與上面等價:

          "Chapter [1-9][0-9]?"
          或者

          "Chapter [1-9][0-9]{0,1}"
          '*'、 '+'和 '?' 限定符都稱之為貪婪的,也就是說,他們盡可能多地匹配文字。有時這根本就不是所希望發生的情況。有時則正好希望最小匹配。

          例如,你可能要搜索一個 HTML 文檔來查找一處包含在 H1 標記中的章節標題。在文檔中該文字可能具有如下形式:

          <H1>Chapter 1 – Introduction to Regular Expressions</H1>
          下面的表達式匹配從開始的小于號 (<) 到 H1 標記結束處的大于號之間的所有內容。

          /<.*>/
          VBScript 的正則表達式為:

          "<.*>"
          如果所要匹配的就是開始的 H1 標記,則下述非貪婪地表達式就只匹配 <H1>。

          /<.*?>/
          或者

          "<.*?>"
          通過在 '*'、 '+' 或 '?' 限定符后放置 '?',該表達式就從貪婪匹配轉為了非貪婪或最小匹配。

          我們都明白
          ()可以為以規則匹配后獲取匹配集合,用RegExp.$1-$9來獲取;
          但規則匹配以非貪婪限制匹配后,將無匹配集合返回;

          我們來討論下非貪婪匹配 與 貪婪匹配
          首先
          (?:pattern)
          匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用 "或" 字符 (|) 來組合一個模式的各個部分是很有用。例如, 'industr(?:y|ies) 就是一個比 'industry|industries' 更簡略的表達式。
          (?=pattern)
          正向預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。
          (?!pattern)
          負向預查,在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始

          什么是貪婪匹配?
          “貪婪匹配”原則是說,當解釋器將代碼中的字符解析成一個個的 編譯器在處理代碼時眼中看到的最小語法單元 時,編譯器會使用一種貪婪匹配算法,也就是說會盡可能讓一個單元包含更多的字符。

          非貪婪匹配的效率
          ? 可能有不少的人和我一樣,有過這樣的經歷:當我們要匹配類似 "<td>內容</td>" 或者 "加粗" 這樣的文本時,我們根據正向預搜索功能寫出這樣的表達式:"<td>([^<]|<(?!/td>))*</td>" 或者 "<td>((?!</td>).)*</td>"。

          ? 當發現非貪婪匹配之時,恍然大悟,同樣功能的表達式可以寫得如此簡單:"<td>.*?</td>"。 頓時間如獲至寶,凡是按邊界匹配的地方,盡量使用簡捷的非貪婪匹配 ".*?"。特別是對于復雜的表達式來說,采用非貪婪匹配 ".*?" 寫出來的表達式的確是簡練了許多。

          ? 然而,當一個表達式中,有多個非貪婪匹配時,或者多個未知匹配次數的表達式時,這個表達式將可能存在效率上的陷阱。有時候,匹配速度慢得莫名奇妙,甚至開始懷疑正則表達式是否實用。

          效率陷阱的產生:

          ? 非貪婪匹配:“如果少匹配就會導致整個表達式匹配失敗的時候,與貪婪模式類似,非貪婪模式會最小限度的再匹配一些,以使整個表達式匹配成功。”

          ? 具體的匹配過程是這樣的:

          "非貪婪部分" 先匹配最少次數,然后嘗試匹配 "右側的表達式"。
          如果右側的表達式匹配成功,則整個表達式匹配結束。如果右側表達式匹配失敗,則 "非貪婪部分" 將增加匹配一次,然后再嘗試匹配 "右側的表達式"。
          如果右側的表達式又匹配失敗,則 "非貪婪部分" 將再增加匹配一次。再嘗試匹配 "右側的表達式"。
          依此類推,最后得到的結果是 "非貪婪部分" 以盡可能少的匹配次數,使整個表達式匹配成功。或者最終仍然匹配失敗。
          ? 當一個表達式中有多個非貪婪匹配,以表達式 "d(\w+?)d(\w+?)z" 為例,對于第一個括號中的 "\w+?" 來說,右邊的 "d(\w+?)z" 屬于它的 "右側的表達式",對于第二個括號中的 "\w+?" 來說,右邊的 "z" 屬于它的 "右側的表達式"。

          ? 當 "z" 匹配失敗時,第二個 "\w+?" 會 "增加匹配一次",再嘗試匹配 "z"。如果第二個 "\w+?" 無論怎樣 "增加匹配次數",直至整篇文本結束,"z" 都不能匹配,那么表示 "d(\w+?)z" 匹配失敗,也就是說第一個 "\w+?" 的 "右側" 匹配失敗。此時,第一個 "\w+?" 會增加匹配一次,然后再進行 "d(\w+?)z" 的匹配。循環前面所講的過程,直至第一個 "\w+?" 無論怎么 "增加匹配次數",后邊的 "d(\w+?)z" 都不能匹配時,整個表達式才宣告匹配失敗。

          ? 其實,為了使整個表達式匹配成功,貪婪匹配也會適當的“讓出”已經匹配的字符。因此貪婪匹配也有類似的情況。當一個表達式中有較多的未知匹配次數的表達式時,為了讓整個表達式匹配成功,各個貪婪或非貪婪的表達式都要進行嘗試減少或增加匹配次數,由此容易形成一個大循環的嘗試,造成了很長的匹配時間。本文之所以稱之為“陷阱”,因為這種效率問題往往不易察覺。

          ? 舉例:"d(\w+?)d(\w+?)d(\w+?)z" 匹配 "ddddddddddd..." 時,將花費較長一段時間才能判斷出匹配失敗 。

          效率陷阱的避免:

          ? 避免效率陷阱的原則是:避免“多重循環”的“嘗試匹配”。并不是說非貪婪匹配就是不好的,只是在運用非貪婪匹配的時候,需要注意避免過多“循環嘗試”的問題。

          ? 情況一:對于只有一個非貪婪或者貪婪匹配的表達式來說,不存在效率陷阱。也就是說,要匹配類似 "<td> 內容 </td>" 這樣的文本,表達式 "<td>([^<]|<(?!/td>))*</td>" 和 "<td>((?!</td>).)*</td>" 和 "<td>.*?</td>" 的效率是完全相同的。

          ? 情況二:如果一個表達式中有多個未知匹配次數的表達式,應防止進行不必要的嘗試匹配。

          ? 比如,對表達式 "<script language='(.*?)'>(.*?)</script>" 來說, 如果前面部分表達式在遇到 "<script language='vbscript'>" 時匹配成功后,而后邊的 "(.*?)</script>" 卻匹配失敗,將導致第一個 ".*?" 增加匹配次數再嘗試。而對于表達式真正目的,讓第一個 ".*?" 增加匹配成“vbscript'>”是不對的,因此這種嘗試是不必要的嘗試。

          ? 因此,對依靠邊界來識別的表達式,不要讓未知匹配次數的部分跨過它的邊界。前面的表達式中,第一個 ".*?" 應該改寫成 "[^']*"。后邊那個 ".*?" 的右邊再沒有未知匹配次數的表達式,因此這個非貪婪匹配沒有效率陷阱。于是,這個匹配腳本塊的表達式,應該寫成:"<script language='([^']*)'>(.*?)</script>" 更好。

          1.貪婪:+,*,?,{m,n}等默認是貪婪匹配,即盡可能多匹配,也叫最大匹配
          如果后面加上?,就轉化為非貪婪匹配,需要高版本支持

          2.獲取:默認用(x|y)是獲取匹配,很多時候只是測試,不一定要求得到所匹配的數據,尤其在嵌套匹配或大數據中就要用非獲取匹配(?:x|y),這樣提高了效率,優化了程序。

          3.消耗:默認是消耗匹配,一般在預查中是非消耗匹配。
          舉個例子,2003-2-8要變為2003-02-08
          如果用/-(\d)-/第二次匹配將從8開始,從而只替換第一個2,錯誤
          如果用/-(\d)(?=-)/則第二次匹配從第二個-開始,即不消耗字符-

          4.預查:js中分為正向預查和負向預查
          如上面的(?=pattern)是正向預查,在任何匹配 pattern 的字符串開始處匹配查找字符串。還有(?!pattern)是負向預查,在任何不匹配 pattern 的字符串開始處匹配查找字符串。負向預查有時會用在對[^]的擴充,[^]只是一些字符,而?!可以使整個字符串。

          5.回調:一般用在替換上,即根據不用的匹配內容返回不用的替換值,從而簡化了程序,需要高版本支持

          6.引用:\num 對所獲取的第num個匹配的引用。
          例如,'(.)\1\1' 匹配AAA型。'(.)(.)\2\1' 匹配ABBA型。

          上面好象有提過正則表達式的界定符.(忘記了沒關系我們再來)
          界定符:一個表達式被包含的區域. 在javascript中我們比較常用的是/作為整體匹配模式的界定符
          在PHP中任何不是字母、數字或反斜線(\)的字符都可以作為定界符。如果作為定界符的字符必須被用在表達式本身中,則需要用反斜線轉義。

          界定符可以分為
          一:整體匹配模式符號
          二:字符類(簇)定界符 例如:[]
          三:子模式符 ();
          四:數量匹配符 {};

          一個模式的建立
          javascript中可以以兩種形式
          一:界定式 例如 var Reg = /^javascript$/ig;
          ? 二:實例化RegExp對象 var Reg = new RegExp("^javascript$","ig");PS:本人一直不喜歡這種形式,只要原因為跟perl規范差很多.有點像PHP的ereg.. 最近也因為這個問題.費了點時間在關于PHP引號中轉義符號的匹配問題.個人建議初學或者為了以后進步才用第一種形式.

          在一個匹配模式建立后.如何使用子模式呢.其實在前面一些正則語法中已經提過了.今天我們再來間單的說下.
          ? 用個典型的例子說明吧
          /<(.*)>.*<\/\1>/ PS:其實這個表達式是有缺陷的,不過我們先不說.
          看了前面幾次的說明,我想應該知道<(.*)>的作用了,那后面的<\/\1>中的第一個\也就是我們文章開頭說的轉義定界符,而\1就是取子模 這里跟javascript的RegExp對象的$0-$9不同是從1開始的.
          也正是如此這個表達式才能匹配簡單的無屬性html標簽 例如<body>body</body>;

          posted on 2007-01-11 13:45 寶貝小豬嘜 閱讀(187) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 海盐县| 甘谷县| 三台县| 滨州市| 茌平县| 正安县| 长垣县| 临颍县| 日喀则市| 琼结县| 呈贡县| 合水县| 塘沽区| 长宁区| 凤城市| 东台市| 古浪县| 井研县| 文昌市| 抚远县| SHOW| 哈巴河县| 班戈县| 乐清市| 大竹县| 体育| 马山县| 板桥市| 义乌市| 德保县| 秦安县| 时尚| 额济纳旗| 玉树县| 孟村| 长武县| 金昌市| 翁牛特旗| 来安县| 常熟市| 天镇县|