JavaScript1.5 正規表達式(Regular Expressions)

正規表達式(Regular Expressions)

正規表達式是使用其相關的樣式(pattern)來比對在字串中的字元組合。

建立正規表達式(Creating a Regular Expression)

您可以由底下兩種方式中,擇一來建構您的正規表達式:

  1. 使用正規表達式的實字敘述方式,例如:

    re = /ab+c/;

    當 Script 被直譯器轉換時,正規表達式的實字提供了正規表達式的編譯(Compilation)。當正規表達式保持不變的時候,使用這種方式將會有較好的效率。

  2. 呼叫正規表達式物件的建構式函式,例如:

    re = new RegExp("ab+c");

    使用建構式函式則提供了正規表達式執行時(Runtime)的編譯。當您知道正規表達式的樣式(Pattern)將會被改變或者您不知道樣式與其從其它來源處取得的話,例如使用者輸入時,則使用建構式函式。

編寫正規表達式的樣式(Writing a Regular Expression Pattern)

正規表達式的樣式是由簡單的字元(Characters)所組合而成,例如 /abc/ 或者由簡單與特殊的字元所組合,例如 /ab*c/ 或 /Chapter (\d+)\.\d*/ 等等。前述最後的例子包含被使用來作為保存設置(memory device)的括號。

使用簡單的樣式(Using Simple Patterns)

簡單的樣式指的是您想要尋找直接匹配(match)的字元所構建的,例如: /abc/ 這個樣式用來比對字串當中的字元組合,只有當這個字元 'abc' 在字串當中正確地以那樣的次序排在一起,才算是比對成功。在字串 "Hi, do you know your abc's?" 與 "The latest airplane designs evolved from slabcraft." 這兩個實例中,如果以子字串(SubString) 'abc' 來比對的話,將會成功的匹配。如果比對字串 "Grab crab" 將不會匹配成功,因為它並不包含子字串 'abc'。

使用特殊的字元(Using Special Characters)

當搜尋比對匹配時,如果需要更多個的直接匹配,例如您想要找尋一個或更多個 b 或者尋找空白(white space)字元的話,則您必須使用含有特殊字元的樣式。例如,樣式 /ab*c/ 比對在任何字元組合中,匹配零個或更多個跟隨在單獨一個 'a' 後面的 'b' 然後緊接著 'c'。

例如,我們以 /ab*c/ 來比對字串 "cbbabbbbcdebc" 時,該樣式則會匹配子字串 'abbbbc'。

以下的表格提供了在正規表達式中,可以被使用之特殊字元的完整清單與其簡單描述:

正規表達式的特殊字元(Special characters in regular expressions)
特殊字元 意義/描述

\

以下其中一個:

  • 跳脫。通常會照著其字義來做處理,指示下一個字元是特殊字元並且它不是照字義來解釋。例如,/b/ 將會匹配字元 'b'。如果在 /b/ 的前面安置一條反斜線 /\b/ 後,該字元則會成為特殊性質的比對文字邊界(word boundary)。
  • 還原。通常會照著其特殊字義來做處理,指示下一個字元不是特殊字元並且它是照字義來解釋。例如,* 是一個特殊的字元,它會比對它前面的字元 0 次或多次來匹配;例如,/a*/ 將匹配 0 次或多次的 a。如果要匹配字串中的 * 實字,則必須在它的前面加上一個反斜線;例如,/a\*/ 將匹配子字串 'a*'。再例如,樣式 /a*\*/ 將匹配 "aaaa*bbbb" 字串中的子字串 'aaaa*'。

^

比對字串的開始,或多列字串的每個開頭。例如,/^A/ 不匹配 "an A" 字串中的子字串 'a',但是它匹配 "An A" 字串中的子字串 'A'。

$

比對字串的結尾,或多列字串的每個結尾。例如,/t$/ 不匹配 "eater" 字串中的子字串 't',但是它匹配 "eat" 字串中的子字串 't'。

*

比對前面的字元 0 次或更多次。例如,/bo*/ 將匹配字串 "A ghost booooed" 中的子字串 'boooo'。/b*/ 將匹配字串 "A bird warbled" 中的子字串 'b'。

+

比對前面的字元 1 次或 1 次以上。例如,/a+/ 將匹配字串 "candy" 中的子字串 'a' 與字串 "caaaaaaandy" 中所有的 'a'。

?

比對前面的字元 0 次或 1 次。例如,/e?le?/ 將匹配 "angel" 字串中的子字串 'el' 與 "angle" 字串中的子字串 'le'。

.

(小數點)比對除了換列(行)字元以外的任何字元。例如,/.n/ 匹配 "nay, an apple is on the tree" 字串中的子字串 'an' 與 'on' 但不匹配子字串 'nay'。

(x)

比對 x 並保存匹配。這些被稱之為捕獲括號。例如,/(foo)/ 將匹配與保存字串 "foo bar." 中的子字串 'foo'。所匹配的子字串可以從陣列元素[1], …, [n] 重新呼叫(作為參考使用)。或者說,比對 x 保存在陣列元素[1],…,[n] 中或比對在正規表達式物件屬性 $1,…,$9 中。

(?:x)

比對 x 但不保存匹配。這些被稱之為非捕獲括號。所匹配的子字串無法從陣列元素[1], …, [n] 重新呼叫(作為參考使用)。

x(?=y)

只有當 x 後面跟隨著 y 才匹配 x。例如,/Jack(?=Sprat)/ 只有當它後面跟隨著 'Sprat' 才匹配 'Jack'。/Jack(?=Sprat|Frost)/ 只有當它後面跟隨著 'Sprat' 或 'Frost' 才匹配 'Jack'。

x(?!y)

只有當 x 後面沒有跟隨著 y 才匹配 x。例如,/\d+(?!\.)/ 只有當它後面沒有跟隨著小數點才匹配一個數值。正規表達式 /\d+(?!\.)/.exec("3.141") 將匹配 '141' 而非 '3.141'。

x|y

比對 x 或 y。例如,/green|red/ 將匹配 "green apple" 字串中的子字串 'green' 與 "red apple" 字串中的子字串 'red'。

{n}

比對 n 次。例如,/a{2}/ 將不匹配 "candy" 字串中的子字串 'a',但是它匹配 "caandy" 字串中所有的 a 與 "caaandy" 字串中第一次的兩個 a。

{n,}

比對 n 次以上。例如,/a{2,}/ 將不匹配 "candy" 中的 a,但是它匹配 "caandy" 字串與 "caaaaaandy" 字串中所有的 a。

{n,m}

比對 n 至 m 次。例如,/a{1,3}/ 將不匹配 "cndy" 中的任何東西,但是它匹配 "candy" 字串中的 a 與 "caandy" 字串中的兩個 a 或者 "caaaaaaandy" 字串中第一次的三個 a。

[xyz]

字元集(character set),比對這個集合中的任何一個字元。您可以透過使用連字號來指定字元的範圍。例如,[abcd] 就如同於 [a-d],它分別將匹配 "brisket" 與 "city" 字串中的子字串 'b' 與 'c'。

[^xyz]

不比對這個集合中的任何一個字元。您可以透過使用連字號來指定字元的範圍。例如,[^abc] 就如同於 [^a-c],它最初分別將匹配 "brisket" 與 "chop" 字串中的子字串 'r' 與 'h'。

[\b]

比對一個倒退鍵字元(Backspace)。(不要與 \b 混淆 )。

\b

比對一個文字邊界(word boundary),像是一個空白字元或一個換列(行)字元(newline)。(不要與 [\b] 混淆 )。例如,/\bn\w/ 將匹配 "noonday" 字串中的子字串 'no';而 /\wy\b/ 將匹配 "possibly yesterday" 字串中的子字串 'ly'。

\B

比對一個非文字邊界(non-word boundary)。例如,/\w\Bn/ 將匹配 "noonday" 字串中的子字串 'on',/y\B\w/ 將匹配 "possibly yesterday" 字串中的子字串 'ye'。

\cX

X 是一個控制字元,比對一個字串中的控制字元。例如,/\cM/ 將匹配一個字串中的 Ctrl-M。

\d

比對一個數字字元,相當於 [0-9]。例如,/\d/ 或 /[0-9]/ 將匹配 "B2 is the suite number" 字串中的子字串 '2'。

\D

比對一個非數字字元,相當於 [^0-9]。例如,/\D/ 或 /[^0-9]/ 將匹配 "B2 is the suite number" 字串中的子字串 'B'。

\f

比對一個跳頁字元。

\n

比對一個換列(行)字元。

\r

比對一個歸位字元。

\s

比對一個單獨的空白字元,包括空白(space)、定位(tab)、跳頁(form-feed)與換列(linefeed)。相當於 [ \f\n\r\t\v\u00A0\u2028\u2029]。例如,/\s\w*/ 將匹配 "foo bar" 字串中的子字串 ' bar'(一個空白接續 bar)。

\S

比對一個空白以外的單獨字元。相當於 [^ \f\n\r\t\v\u00A0\u2028\u2029]。例如,/\S\w*/ 將匹配 "foo bar" 字串中的子字串 'foo'。

\t

比對一個定位(tab)字元。

\v

比對一個垂直定位(vertical tab)字元。

\w

比對任意的英數字元,包括底線(underscore)。相當於 [A-Za-z0-9_]。例如,/\w/ 將匹配 "apple" 字串中的子字串 'a',"$5.28" 字串中的子字串 '5',"3D" 字串中的子字串 '3'。

\W

比對任意的非文字(non-word)字元。相當於 [^A-Za-z0-9_]。例如,/\W/ 或 /[^A-Za-z0-9_]/ 將匹配 "50%" 字串的子字串 '%'。

\n

左邊的 n 為一個正整數。返回比對在正規表達式 n 括號(群組)最後一個字字串的參考(計數左邊的括號)。例如,/apple(,)\sorange\1/ 將匹配 "apple, orange, cherry, peach" 字串中的子字串 'apple, orange,'。

\0

比對一個 NULL 字元。後面不要跟隨其它的數字。

\xhh

比對 16 進位的 hh 字元(2 個 16 進位的值)。

\uhhhh

比對 16 進位的 hhhh 字元(4 個 16 進位的值)。

使用括號(Using Parentheses)

在正規表達式樣式中,括號內的任何部分,其所匹配的子字串將會被保存。一旦保存,所匹配的子字串將可以重新呼叫(recall)來作為其它的使用,例如在使用括號內匹配的子字串中的描述。

例如,樣式 /Chapter (\d+)\.\d*/ 描述了跳脫(escaped)與特殊字元和指示樣式應該被保存的部分。它比對某字串的字元 'Chapter ' 與跟隨在它之後的數字字元一次或更多次(\d 意指任何數字字元而 + 表示一次或更多次),其後再跟隨著小數點(它自身為一個特殊字元;小數點前的 \ 號意指樣式必須尋找實字字元 '.'),其後再接續 0 次或更多次的任何數字字元(\d 意指數字字元,* 表示 0 或更多次)。此外,該樣式的括號被使用在保存第一次所匹配的數字字元。

如果上述的樣式用於 "Open Chapter 4.3, paragraph 6" 字串,'4' 將會被保存。如果該樣式用於 "Chapter 3 and 4" 字串將無法匹配,因為在 '3' 之後並沒有接續一段字串(小數點)。

如果要匹配一個子字串並且不會造成所匹配的部分被保存,可以在括號內以樣式 ?: 作為開端。例如,樣式 (?:\d+) 可以匹配一次或更多次的數字字元,但它並不會保存所匹配的字元。

正規表達式的操作(Working with Regular Expressions)

正規表達式的操作(Working with Regular Expressions)

正規表達式是以 RegExp 的方法 test 與 exec 或者我們在字串當中以 match、replace、search 和 split 等等方法來使用。

請參閱底下兩個內建的核心物件:

使用括號內匹配的子字串(Using Parenthesized Substring Matches)

在正規表達式中,其樣式所包含的括號會導致相對應的子匹配(submatch)被保存。例如,樣式 /a(b)c/ 匹配字元 'abc' 並且保存了 'b'。如果要重新呼叫(recall)這些在弧號內匹配的子字串,可以使用陣列元素 [1], …, [n]。

在括號內可能的子字串數目是無限的;只要在回傳的陣列中可以找到的話,就可以擁有。以下的範例說明了如何來使用括號內匹配的子字串。

範例:

底下的 Script 使用 replace 方法來置換字串中的文字。為了要置換文字,該 Script 使用了 $1 與 $2 來置換第一個和第二個括號內匹配的子字串。

	re = /(\w+)\s(\w+)/;
	str = "John Smith";
	newstr = str.replace(re, "$2, $1");
	document.write(newstr);

上述範例的結果顯示:Smith, John

文章分類

文章標籤