Regular Expression

建立一個正則表達式

你可使用如下兩種方法之一構建一個正則表達式:html

使用一個正則表達式字面量,其由包含在斜槓之間的模式組成,以下所示:git

/* /pattern/flags */ const regex = /ab+c/; const regex = /^[a-zA-Z]+[0-9]*\W?_$/gi;

在加載腳本後,正則表達式字面值提供正則表達式的編譯。當正則表達式保持不變時,使用此方法可得到更好的性能。es6

或者調用RegExp對象的構造函數,以下所示:正則表達式

/* new RegExp(pattern [, flags]) */ let regex = new RegExp("ab+c"); let regex = new RegExp(/^[a-zA-Z]+[0-9]*\W?_$/, "gi"); let regex = new RegExp("^[a-zA-Z]+[0-9]*\\W?_$", "gi");

使用構造函數提供正則表達式的運行時編譯。使用構造函數,當你知道正則表達式模式將會改變,或者你不知道模式,並從另外一個來源,如用戶輸入。數組

編寫一個正則表達式的模式

一個正則表達式模式是由簡單的字符所構成的,好比/abc/, 或者是簡單和特殊字符的組合,好比 /ab*c/ 或 /Chapter (\d+)\.\d*/。後者用到了括號,它在正則表達式中能夠被用做是一個記憶設備。這一部分正則所匹配的字符將會被記住,在後面能夠被利用。正如 使用括號的子字符串匹配app

使用簡單的模式

簡單的模式是由你找到的直接匹配所構成的。好比,/abc/這個模式就匹配了在一個字符串中,僅僅字符 'abc' 同時出現並按照這個順序。在 "Hi, do you know your abc's?" 和 "The latest airplane designs evolved from slabcraft." 就會匹配成功。在上面的兩個實例中,匹配的是子字符串 'abc'。在字符串 "Grab crab" 中將不會被匹配,由於它不包含任何的 'abc' 子字符串。ide

使用特殊字符

當你須要搜索一個比直接匹配須要更多條件的匹配時,好比尋找一個或多個 'b',或者尋找空格,那麼這時模式將要包含特殊字符。好比, 模式/ab*c/匹配了一個單獨的 'a' 後面跟了零個或者多個 'b'(*的意思是前面一項出現了零個或者多個),且後面跟着 'c' 的任何字符組合。在字符串 "cbbabbbbcdebc" 中,這個模式匹配了子字符串 "abbbbc"。函數

下面的表格列出了一個咱們在正則表達式中能夠利用的特殊字符的完整列表和描述。grunt

表 4.1 正則表達式中的特殊字符
字符 含義
\

匹配將依照下列規則:性能

在非特殊字符以前的反斜槓表示下一個字符是特殊的,不能從字面上解釋。例如,沒有前面'\'的'b'一般匹配小寫'b',不管它們出如今哪裏。若是加了'\',這個字符變成了一個特殊意義的字符,意思是匹配一個字符邊界

反斜槓也能夠將其後的特殊字符,轉義爲字面量。例如,模式 /a*/ 表明會匹配 0 個或者多個 a。相反,模式 /a\*/ 將 '*' 的特殊性移除,從而能夠匹配像 "a*" 這樣的字符串。

使用 new RegExp("pattern") 的時候不要忘記將 \ 進行轉義,由於 \ 在字符串裏面也是一個轉義字符。

^

匹配輸入的開始。若是多行標誌被設置爲true,那麼也匹配換行符後緊跟的位置。

例如,/^A/ 並不會匹配 "an A" 中的 'A',可是會匹配 "An E" 中的 'A'。

當 '^' 做爲第一個字符出如今一個字符集合模式時,它將會有不一樣的含義。補充字符集合 一節有詳細介紹和示例。

$

匹配輸入的結束。若是多行標示被設置爲true,那麼也匹配換行符前的位置。

例如,/t$/ 並不會匹配 "eater" 中的 't',可是會匹配 "eat" 中的 't'。

*

匹配前一個表達式0次或屢次。等價於 {0,}。

例如,/bo*/會匹配 "A ghost boooooed" 中的 'booooo' 和 "A bird warbled" 中的 'b',可是在 "A goat grunted" 中將不會匹配任何東西。

+

匹配前面一個表達式1次或者屢次。等價於 {1,}。

例如,/a+/匹配了在 "candy" 中的 'a',和在 "caaaaaaandy" 中全部的 'a'。

?

匹配前面一個表達式0次或者1次。等價於 {0,1}。

例如,/e?le?/ 匹配 "angel" 中的 'el',和 "angle" 中的 'le' 以及"oslo' 中的'l'。

若是緊跟在任何量詞 *、 +、? 或 {} 的後面,將會使量詞變爲非貪婪的(匹配儘可能少的字符),和缺省使用的貪婪模式(匹配儘量多的字符)正好相反。

例如,對 "123abc" 應用 /\d+/ 將會返回 "123",若是使用 /\d+?/,那麼就只會匹配到 "1"。

還能夠運用於先行斷言,如本表的 x(?=y) 和 x(?!y) 條目中所述。

.

(小數點)匹配除換行符以外的任何單個字符。

例如,/.n/將會匹配 "nay, an apple is on the tree" 中的 'an' 和 'on',可是不會匹配 'nay'。

(x)

匹配 'x' 而且記住匹配項,就像下面的例子展現的那樣。括號被稱爲 捕獲括號

模式/(foo) (bar) \1 \2/中的 '(foo)' 和 '(bar)' 匹配並記住字符串 "foo bar foo bar" 中前兩個單詞。模式中的 \1 和 \2 匹配字符串的後兩個單詞。注意 \一、\二、\n 是用在正則表達式的匹配環節。在正則表達式的替換環節,則要使用像 $一、$二、$n 這樣的語法,例如,'bar foo'.replace( /(...) (...)/, '$2 $1' )。

(?:x)

匹配 'x' 可是不記住匹配項。這種叫做非捕獲括號,使得你可以定義爲與正則表達式運算符一塊兒使用的子表達式。來看示例表達式 /(?:foo){1,2}/。若是表達式是 /foo{1,2}/,{1,2}將只對 ‘foo’ 的最後一個字符 ’o‘ 生效。若是使用非捕獲括號,則{1,2}會匹配整個 ‘foo’ 單詞。

x(?=y)

匹配'x'僅僅當'x'後面跟着'y'.這種叫作正向確定查找。

例如,/Jack(?=Sprat)/會匹配到'Jack'僅僅當它後面跟着'Sprat'。/Jack(?=Sprat|Frost)/匹配‘Jack’僅僅當它後面跟着'Sprat'或者是‘Frost’。可是‘Sprat’和‘Frost’都不是匹配結果的一部分。

x(?!y)

匹配'x'僅僅當'x'後面不跟着'y',這個叫作正向否認查找。

例如,/\d+(?!\.)/匹配一個數字僅僅當這個數字後面沒有跟小數點的時候。正則表達式/\d+(?!\.)/.exec("3.141")匹配‘141’可是不是‘3.141’

x|y

匹配‘x’或者‘y’。

例如,/green|red/匹配「green apple」中的‘green’和「red apple」中的‘red’

{n}

n是一個正整數,匹配了前面一個字符恰好發生了n次。

好比,/a{2}/不會匹配「candy」中的'a',可是會匹配「caandy」中全部的a,以及「caaandy」中的前兩個'a'。

{n,m}

n 和 m 都是整數。匹配前面的字符至少n次,最多m次。若是 n 或者 m 的值是0, 這個值被忽略。

例如,/a{1, 3}/ 並不匹配「cndy」中的任意字符,匹配「candy」中的a,匹配「caandy」中的前兩個a,也匹配「caaaaaaandy」中的前三個a。注意,當匹配」caaaaaaandy「時,匹配的值是「aaa」,即便原始的字符串中有更多的a。

[xyz]

一個字符集合。匹配方括號的中任意字符,包括轉義序列。你可使用破折號(-)來指定一個字符範圍。對於點(.)和星號(*)這樣的特殊符號在一個字符集中沒有特殊的意義。他們沒必要進行轉義,不過轉義也是起做用的。

例如,[abcd] 和[a-d]是同樣的。他們都匹配"brisket"中得‘b’,也都匹配「city」中的‘c’。/[a-z.]+/ 和/[\w.]+/都匹配「test.i.ng」中的全部字符。

[^xyz]

一個反向字符集。也就是說, 它匹配任何沒有包含在方括號中的字符。你可使用破折號(-)來指定一個字符範圍。任何普通字符在這裏都是起做用的。

例如,[^abc] 和 [^a-c] 是同樣的。他們匹配"brisket"中的‘r’,也匹配「chop」中的‘h’。

[\b]

匹配一個退格(U+0008)。(不要和\b混淆了。)

\b

匹配一個詞的邊界。一個詞的邊界就是一個詞不被另一個「字」字符跟隨的位置或者沒有其餘「字」字符在其前面的位置。注意,一個匹配的詞的邊界並不包含在匹配的內容中。換句話說,一個匹配的詞的邊界的內容的長度是0。(不要和[\b]混淆了)

例子:

/\bm/匹配「moon」中得‘m’;

/oo\b/並不匹配"moon"中得'oo',由於'oo'被一個「字」字符'n'緊跟着。

/oon\b/匹配"moon"中得'oon',由於'oon'是這個字符串的結束部分。這樣他沒有被一個「字」字符緊跟着。

/\w\b\w/將不能匹配任何字符串,由於在一個單詞中間的字符永遠也不可能同時知足沒有「字」字符跟隨和有「字」字符跟隨兩種狀況。

注意: JavaScript的正則表達式引擎將特定的字符集定義爲「字」字符。不在該集合中的任何字符都被認爲是一個斷詞。這組字符至關有限:它只包括大寫和小寫的羅馬字母,十進制數字和下劃線字符。不幸的是,重要的字符,例如「é」或「ü」,被視爲斷詞。

\B

匹配一個非單詞邊界。他匹配一個先後字符都是相同類型的位置:都是「字」字符或者都不是「字」字符。一個字符串的開始和結尾都被認爲不是「字」字符,或者空字符串。

例如,/\B../匹配"noonday"中的'oo', 而/y\B../匹配"possibly yesterday"中的’yes‘

\cX

當X是處於A到Z之間的字符的時候,匹配字符串中的一個控制符。

例如,/\cM/ 匹配字符串中的 control-M (U+000D)。

\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 匹配一個換頁符 (U+000C)。
\n 匹配一個換行符 (U+000A)。
\r 匹配一個回車符 (U+000D)。
\s

匹配一個空白字符,包括空格、製表符、換頁符和換行符。

等價於[ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。

例如, /\s\w*/ 匹配"foo bar."中的' bar'。

\S

匹配一個非空白字符。

等價於[^ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]

例如, /\S\w*/ 匹配"foo bar."中的'foo'。

\t 匹配一個水平製表符 (U+0009)。
\v 匹配一個垂直製表符 (U+000B)。
\w

匹配一個單字字符(字母、數字或者下劃線)。

等價於[A-Za-z0-9_]

例如, /\w/ 匹配 "apple," 中的 'a',"$5.28,"中的 '5' 和 "3D." 中的 '3'。

\W

匹配一個非單字字符。

等價於[^A-Za-z0-9_]

例如, /\W/ 或者 /[^A-Za-z0-9_]/ 匹配 "50%." 中的 '%'。

\n

在正則表達式中,它返回最後的第n個子捕獲匹配的子字符串(捕獲的數目以左括號計數)。

好比 /apple(,)\sorange\1/ 匹配"apple, orange, cherry, peach."中的'apple, orange,' 。

\0 匹配 NULL (U+0000) 字符, 不要在這後面跟其它小數,由於 \0<digits> 是一個八進制轉義序列。
\xhh 與代碼 hh 匹配字符(兩個十六進制數字)
\uhhhh 與代碼 hhhh 匹配字符(四個十六進制數字)。
\u{hhhh} (僅當設置了u標誌時) 使用Unicode值hhhh匹配字符 (十六進制數字).

將用戶輸入轉義爲正則表達式中的一個字面字符串, 能夠經過簡單的替換來實現:

function escapeRegExp(string){
    return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$&"); 
    //$&表示整個被匹配的字符串
}

使用插入語

任何正則表達式的插入語都會使這部分匹配的副字符串被記憶。一旦被記憶,這個副字符串就能夠被調用於其它用途,如同 使用括號的子字符串匹配之中所述。

好比, /Chapter (\d+)\.\d*/ 解釋了額外轉義的和特殊的字符,並說明了這部分pattern應該被記憶。它精確地匹配後面跟着一個以上數字字符的字符 'Chapter '  (\d 意爲任何數字字符,+ 意爲1次以上),跟着一個小數點(在這個字符中自己也是一個特殊字符;小數點前的 \ 意味着這個pattern必須尋找字面字符 '.'),跟着任何數字字符0次以上。 (\d 意爲數字字符, * 意爲0次以上)。另外,插入語也用來記憶第一個匹配的數字字符。

此模式能夠匹配字符串"Open Chapter 4.3, paragraph 6",而且'4'將會被記住。此模式並不能匹配"Chapter 3 and 4",由於在這個字符串中'3'的後面沒有點號'.'。

括號中的"?:",這種模式匹配的子字符串將不會被記住。好比,(?:\d+)匹配一次或屢次數字字符,可是不能記住匹配的字符。

使用正則表達式

正則表達式能夠被用於RegExpexectest方法以及 Stringmatchreplacesearchsplit方法。這些方法在JavaScript 手冊中有詳細的解釋。

表 4.2 使用正則表達式的方法
方法 描述
exec 一個在字符串中執行查找匹配的RegExp方法,它返回一個數組(未匹配到則返回null)。
test 一個在字符串中測試是否匹配的RegExp方法,它返回true或false。
match 一個在字符串中執行查找匹配的String方法,它返回一個數組或者在未匹配到時返回null。
search 一個在字符串中測試匹配的String方法,它返回匹配到的位置索引,或者在失敗時返回-1。
replace 一個在字符串中執行查找匹配的String方法,而且使用替換字符串替換掉匹配到的子字符串。
split 一個使用正則表達式或者一個固定字符串分隔一個字符串,並將分隔後的子字符串存儲到數組中的String方法。

當你想要知道在一個字符串中的一個匹配是否被找到,你可使用test或search方法;想獲得更多的信息(可是比較慢)則可使用exec或match方法。若是你使用exec或match方法而且匹配成功了,那麼這些方法將返回一個數組而且更新相關的正則表達式對象的屬性和預約義的正則表達式對象(詳見下)。若是匹配失敗,那麼exec方法返回null(也就是false)。

在接下來的例子中,腳本將使用exec方法在一個字符串中查找一個匹配。

var myRe = /d(b+)d/g;
var myArray = myRe.exec("cdbbdbsbz");

若是你不須要訪問正則表達式的屬性,這個腳本經過另外一個方法來建立myArray:

var myArray = /d(b+)d/g.exec("cdbbdbsbz");

若是你想經過一個字符串構建正則表達式,那麼這個腳本還有另外一種方法:

var myRe = new RegExp("d(b+)d", "g");
var myArray = myRe.exec("cdbbdbsbz");

經過這些腳本,匹配成功後將返回一個數組而且更新正則表達式的屬性,以下表所示。

表 4.3 正則表達式執行返回信息
對象 屬性或索引 描述 在例子中對應的值
myArray   匹配到的字符串和全部被記住的子字符串。 ["dbbd", "bb"]
index 在輸入的字符串中匹配到的以0開始的索引值。 1
input 初始字符串。 "cdbbdbsbz"
[0] 匹配到的全部字符串(並非匹配後記住的字符串)。注:原文"The last matched characters.",應該是原版錯誤。匹配到的最終字符。 "dbbd"
myRe lastIndex 下一個匹配的索引值。(這個屬性只有在使用g參數時可用在 經過參數進行高級搜索 一節有詳細的描述.) 5
source 模式文本。在正則表達式建立時更新,不執行。 "d(b+)d"

在這個例子中如第二種形式所示,你可使用一個正則表達式建立一個沒有分配給變量的對象初始化容器。若是你這樣作,那麼,每一次使用時都比如在使用一個新的正則表達式。由於這個緣由,若是你使用這個未分配給一個變量的正則表達式,你將在隨後不能訪問這個正則表達式的屬性。例如,假如你有以下腳本:

var myRe = /d(b+)d/g;
var myArray = myRe.exec("cdbbdbsbz");
console.log("The value of lastIndex is " + myRe.lastIndex);

這個腳本輸出以下:

The value of lastIndex is 5

然而,若是你有以下腳本:

var myArray = /d(b+)d/g.exec("cdbbdbsbz");
console.log("The value of lastIndex is " + /d(b+)d/g.lastIndex);

它顯示爲:

The value of lastIndex is 0

當發生/d(b+)d/g使用兩個不一樣狀態的正則表達式對象,lastIndex屬性會獲得不一樣的值。若是你須要訪問一個正則表達式的屬性,則須要建立一個對象初始化生成器,你應該首先把它賦值給一個變量。

使用括號的子字符串匹配

一個正則表達式模式使用括號,將致使相應的子匹配被記住。例如,/a(b)c /能夠匹配字符串「abc」,而且記得「b」。回調這些括號中匹配的子串,使用數組元素[1],……[n]。

使用括號匹配的子字符串的數量是無限的。返回的數組中保存全部被發現的子匹配。下面的例子說明了如何使用括號的子字符串匹配。

下面的腳本使用replace()方法來轉換字符串中的單詞。在匹配到的替換文本中,腳本使用替代的$ 1,$ 2表示第一個和第二個括號的子字符串匹配。

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

這個表達式輸出 "Smith, John"。

經過標誌進行高級搜索

正則表達式有四個可選參數進行全局和不分大小寫搜索。這些參數既能夠單獨使用也能夠一塊兒使用在任何順序和包含正則表達式的部分中。

正則表達式標誌
標誌 描述
g 全局搜索。
i 不區分大小寫搜索。
m 多行搜索。
y 執行「粘性」搜索,匹配從目標字符串的當前位置開始,可使用y標誌。

包含一個標誌的正則表達式,使用這個表達式:

var re = /pattern/flags;

或者

var re = new RegExp("pattern", "flags");

值得注意的是,標誌是一個正則表達式的一部分,它們在接下來的時間將不能添加或刪除。

例如,re = /\w+\s/g 將建立一個查找一個或多個字符後有一個空格的正則表達式,或者組合起來像此要求的字符串。

var re = /\w+\s/g;
var str = "fee fi fo fum";
var myArray = str.match(re);
console.log(myArray);

這段代碼將輸出 ["fee ", "fi ", "fo "]。在這個例子中,你能夠將:

var re = /\w+\s/g;

替換成:

var re = new RegExp("\\w+\\s", "g");

而且能獲取到相同的結果。

m標誌用於指定多行輸入字符串應該被視爲多個行。若是使用m標誌,^和$匹配的開始或結束輸入字符串中的每一行,而不是整個字符串的開始或結束。

相關文章
相關標籤/搜索