天天看點

JavaScript 正規表達式

1. 正規表達式建立

JavaScript 有兩種方式建立正規表達式:

  • 第一種:直接通過/正規表達式/寫出來
  • 第二種:通過new RegExp('正規表達式')建立一個RegExp對象
const re1 = /ABC\-001/;
const re2 = new RegExp('ABC\\-001');

re1; // /ABC\-001/
re2; // /ABC\-001/
           

注意,如果使用第二種寫法,因為字元串的轉義問題,字元串的兩個\實際上是一個\。

2. 使用模式

2.1 使用簡單模式

簡單的模式是由找到的直接比對所構成的。比如,/abc/這個模式就比對了在一個字元串中,僅僅字元 'abc' 同時出現并按照這個順序。在 "Hi, do you know your abc's?" 和 "The latest airplane designs evolved from slabcraft." 就會比對成功。在上面的兩個執行個體中,比對的是子字元串 'abc'。在字元串 "Grab crab" 中将不會被比對,因為它不包含任何的 'abc' 子字元串。

2.2 使用特殊字元

例如:模式/abc/比對了一個單獨的 'a' 後面跟了零個或者多個 'b'(的意思是前面一項出現了零個或者多個),且後面跟着 'c' 的任何字元組合。在字元串 "s'scbbabbbbcdebc" 中,這個模式比對了子字元串 "abbbbc"。

字元 含義
\

比對将依照下列規則:

在非特殊字元之前的反斜杠表示下一個字元是特殊的,不能從字面上解釋。例如,前面沒有''的'd'通常比對小寫'd'。如果加了'',這個字元變成了一個特殊意義的字元,意思是比對一個數字。

反斜杠也可以将其後的特殊字元,轉義為字面量。例如,模式 /a/ 代表會比對 0 個或者多個 a。相反,模式 /a*/ 将 '' 的特殊性移除,進而可以比對像 "a*" 這樣的字元串。

使用 new RegExp("pattern") 的時候也不要忘記将 \ 進行轉義,因為 \ 在字元串裡面也是一個轉義字元。

^ 比對輸入的開始,例如,

/^A/

并不會比對 "an A" 中的 'A',但是會比對 "An E" 中的 'A'。
$ 比對輸入的結束。例如,/t$/ 并不會比對 "eater" 中的 't',但是會比對 "eat" 中的 't'。
  • | 比對前一個表達式0次或多次。等價于 {0,}。例如,/bo*/會比對 "A ghost boooooed" 中的 'booooo'
  • | 比對前面一個表達式1次或者多次。等價于 {1,}。例如,/a+/比對了在 "candy" 中的 'a',和在 "caaaaaaandy" 中所有的 'a'。

    ? | 比對前面一個表達式0次或者1次。等價于 {0,1}。例如,/e?le?/ 比對 "angel" 中的 'el',和 "angle" 中的 'le' 以及"oslo' 中的'l'。

    如果緊跟在任何量詞 、 +、? 或 {} 的後面,将會使量詞變為非貪婪的(比對盡量少的字元),和預設使用的貪婪模式(比對盡可能多的字元)正好相反。

    例如,對 "123abc" 應用 /\d+/ 将會傳回 "123",如果使用 /\d+?/,那麼就隻會比對到 "1"。

    . | 比對除換行符之外的任何單個字元。例如,/.n/将會比對 "nay, an apple is on the tree" 中的 'an' 和 'on',但是不會比對 'nay'。

    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] | 一個反向字元集。也就是說, 它比對任何沒有包含在方括号中的字元。你可以使用破折号(-)來指定一個字元範圍。任何普通字元在這裡都是起作用的。

    \b | 比對一個詞的邊界。一個詞的邊界就是一個詞不被另外一個“字”字元跟随的位置或者沒有其他“字”字元在其前面的位置。注意,一個比對的詞的邊界并不包含在比對的内容中。換句話說,一個比對的詞的邊界的内容的長度是0。例如:

    /\bm/比對“moon”中的‘m’;/oo\b/并不比對"moon"中的'oo',因為'oo'被一個“字”字元'n'緊跟着。/oon\b/比對"moon"中的'oon',因為'oon'是這個字元串的結束部分。這樣他沒有被一個“字”字元緊跟着。

    \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)。

    \w | 比對一個單字字元(字母、數字或者下劃線)。等價于[A-Za-z0-9_]。

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

    \W | 比對一個非單字字元。

    \n | 在正規表達式中,它傳回最後的第n個子捕獲比對的子字元串(捕獲的數目以左括号計數)。

3. 應用

3.1 切分字元串

用正規表達式切分字元串比用固定的字元更靈活,通常的切分代碼:

'a d   c'.split(' '); // ['a', 'd', '', '', 'c']
           

上面方法無法識别連續的空格,改用正規表達式:

'a b   c'.split(/\s+/); // ['a', 'b', 'c']
           

無論多少個空格都可以正常分割。再加入‘,’:

'a,b, c  d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
           

再加入;:

'a,b;; c  d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']
           

是以,可以用正規表達式來把不規範的輸入轉化成正确的數組。

3.2 分組

除了判斷是否比對之外,正規表達式還可以提取子串,用()表示的就是要提取的分組(Group)。比如:

^(\d{4})-(\d{4,9})$

分别定義了兩個組,可以直接從比對的字元串中提取出區号和本地号碼:

var re = /^(\d{4})-(\d{4,9})$/;
re.exec('0530-12306'); // ['010-12345', '010', '12345']
re.exec('0530 12306'); // null
           

exec()方法在比對成功後,傳回一個數組,第一個元素是正規表達式比對到的整個字元串,後面的字元串表示比對成功的子串。

exec()方法在比對失敗時傳回null。

3.3 貪婪比對

注意,正則比對預設是貪婪比對,也就是比對盡可能多的字元。如下,比對出數字後面的0:

var re = /^(\d+)(0*)$/;
re.exec('102300'); // ['102300', '102300', '']
           

由于

\d+

采用貪婪比對,直接把後面的

全部比對了,結果

0*

隻能比對空字元串了。

必須讓

\d+

采用非貪婪比對(也就是盡可能少比對),才能把後面的

比對出來,加個

?

就可以讓

\d+

采用非貪婪比對:

var re = /^(\d+?)(0*)$/;
re.exec('102300'); // ['102300', '1023', '00']
           

3.4 正規表達式标志

g	全局搜尋。
i	不區分大小寫搜尋。
m	多行搜尋。
y	執行“粘性”搜尋,比對從目标字元串的目前位置開始,可以使用y标志。
           

3.6 test() 方法

test() 方法用于檢測一個字元串是否比對某個模式,如果字元串中含有比對的文本,則傳回 true,否則傳回 false。

var re = /^(\d{4})-(\d{4,9})$/;
re.test('0530-12321'); // true
re.test('0530-123ab'); // false
re.test('0530 12321'); // false
           

4. 常用正則(參考)

驗證Email位址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
驗證身份證号(15位或18位數字):^\d{15}|\d{}18$

中國大陸手機号碼:1\d{10}
中國大陸固定電話号碼:(\d{4}-|\d{3}-)?(\d{8}|\d{7})
中國大陸郵政編碼:[1-9]\d{5}

IP位址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

日期(年-月-日):(\d{4}|\d{2})-((1[0-2])|(0?[1-9]))-(([12][0-9])|(3[01])|(0?[1-9]))
日期(月/日/年):((1[0-2])|(0?[1-9]))/(([12][0-9])|(3[01])|(0?[1-9]))/(\d{4}|\d{2})


驗證數字:^[0-9]*$
驗證n位的數字:^\d{n}$
驗證至少n位數字:^\d{n,}$
驗證m-n位的數字:^\d{m,n}$
驗證零和非零開頭的數字:^(0|[1-9][0-9]*)$
驗證有1-3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$
驗證非零的正整數:^\+?[1-9][0-9]*$
驗證非零的負整數:^\-[1-9][0-9]*$
驗證非負整數(正整數 + 0) ^\d+$
驗證非正整數(負整數 + 0) ^((-\d+)|(0+))$
驗證長度為3的字元:^.{3}$
驗證由26個英文字母組成的字元串:^[A-Za-z]+$
驗證由26個大寫英文字母組成的字元串:^[A-Z]+$
驗證由26個小寫英文字母組成的字元串:^[a-z]+$
驗證由數字和26個英文字母組成的字元串:^[A-Za-z0-9]+$

           

繼續閱讀