03標準對象-02-RegExp 正則表達式

一、基本概念 和 定義

用一種描述性的語言來給字符串定義一個規則,你能夠形象地理解正則表達式是一個「框」,凡是符合大小形狀條件的字符串,都算是「匹配「了。

JS中有兩種方式定義正則表達式:
  • 經過 /正則表達式/ 寫出來;
  • 經過 new RegExp(' 正則表達式 ') 建立RegExp對象
var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');  //這裏的兩個\\由於轉義,其實是一個\ 

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

二、匹配規則

在正則表達式中,若是 直接給出字符,表示精確匹配,其餘的根據規則不一樣匹配不一樣內容。特殊符號用轉義字符 \ 表示。

例如咱們想匹配如 ' 010-12345 ' 這樣的號碼,咱們的正則表達式能夠是: \d{3}\-\d{3, 8}:短橫線前要求3個數字,以後要求3到8個數字。

2.1 匹配內容

\d     匹配一個數字
\w 匹配一個字母或數字
\s 匹配一個空格
. (點)能夠匹配任意字符

2.2 基本匹配

* 表示任意個字符(包括0個)
+ 表示至少一個字符
? 表示0個或1個字符
{n} 表示n個字符
{n,m} 表示n-m個字符

2.3 高級匹配

要作更精確地匹配,能夠使用中括號 [ ] 表示範圍
[0-9a-zA-Z\_] 匹配一個數字、字母或者下劃線
[0-9a-zA-Z\_]+  匹配至少由一個數字、字母或下劃線組成的字符串,如 'a100', '0_Z'
[a-zA-Z\_\$][0-9a-zA-Z\_\$]* 能夠匹配由字母或下劃線、$開頭,後接任意一數字、字母、下劃線、$組成的字符串,也就是JS容許的變量名
[a-zA-Z\_\$][0-9a-zA-Z\_\$]{0, 19} 相比以上,更加精確地限制了變量的長度是1-20個字符(前面1個字符,後面最多19個字符)
A | B     匹配A或B,如 (J | j)S 能夠匹配 'JS' 或 'jS'
^     表示行的開頭,如 ^\d 表示必須數字開頭
$ 表示行的結尾,如 \d$ 表示必須以數字結尾 

三、正則表達式的應用

3.1 切分字符串


//正常的切分代碼:沒法識別連續的空格
'a b   c'.split(' '); // ['a', 'b', '', '', '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 分組(子串提取)

正則表達式還能夠提取子串,用 括號 ( ) 表示的就是要提取的分組

好比:^(\d{3})-(\d{3,8})$分別定義了兩個組,能夠直接從匹配的字符串中提取出區號和本地號碼:

var re = /^(\d{3})-(\d{3,8})$/;
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null

若是正則表達式中定義了組,能夠在RegExp對象中使用 exec()方法提取子串,匹配成功後,返回一個Array,第一個元素是正則表達式匹配到的整個字符串,後面的字符串表示匹配成功的子串;匹配失敗會返回null。

對於提取子串,再看一個長點的例子:

var re = /^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$/;
re.exec('19:05:30'); // ['19:05:30', '19', '05', '30']

上面的正則表達式能夠識別合法的時間,但有些時候,正則表達式也沒法徹底作到驗證,好比識別日期,像2-30此類還識別不了,或者寫出來很是困難。

3.3 貪婪匹配

正則匹配默認是貪婪匹配,也就是匹配儘量多的字符。

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

//因爲\d+採用貪婪匹配,直接把後面的0所有匹配了,結果0*只能匹配空字符串了。

必須讓 \d+ 非貪婪匹配,才能把後面的0匹配出來, 加個 ? 就可讓 \d+ 採用非貪婪匹配

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

3.4 全局搜索

g     表示全局匹配
i     表示忽略大小寫
m     表示多行匹配
var r1 = /test/g;
// 等價於:
var r2 = new RegExp('test', 'g');

全局匹配能夠屢次執行exec()方法來搜索一個匹配的字符串。當咱們指定g標誌後,每次運行exec(),正則表達式自己會更新lastIndex屬性,表示上次匹配到的最後索引:
var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g;

// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10

re.exec(s); // ['VBScript']
re.lastIndex; // 20

re.exec(s); // ['JScript']
re.lastIndex; // 29

re.exec(s); // ['ECMAScript']
re.lastIndex; // 44

re.exec(s); // null,直到結束仍沒有匹配到

四、思惟拓展練習

4.1 嘗試寫一個驗證Email地址的正則表達式

Email地址驗證的正則表達式,要求只能字母開頭

'use strict';
var re = /^[a-zA-Z][a-zA-Z\d\_\.]*@[a-zA-Z\d]+\.[a-zA-Z]{2,3}$/;

// 測試:
var
    i,
    success = true,
    should_pass = ['someone@gmail.com', 'bill.gates@microsoft.com', 'tom@voyager.org', 'bob2015@163.com'],
    should_fail = ['test#gmail.com', 'bill@microsoft', 'bill%gates@ms.com', '@voyager.org'];
for (i = 0; i < should_pass.length; i++) {
    if (!re.test(should_pass[i])) {
        alert('測試失敗: ' + should_pass[i]);
        success = false;
        break;
    }
}
for (i = 0; i < should_fail.length; i++) {
    if (re.test(should_fail[i])) {
        alert('測試失敗: ' + should_fail[i]);
        success = false;
        break;
    }
}
if (success) {
    alert('測試經過!');
}

4.2 驗證並提取出帶名字的Email地址


'use strict';
var re = /^\<([a-zA-Z\s]+)\>\s([a-zA-Z][a-zA-Z\d\_\.]*@[a-zA-Z\d]+\.[a-zA-Z]{2,3})$/;

// 測試:
var r = re.exec('<Tom Paris> tom@voyager.org');
if (r === null || r.toString() !== ['<Tom Paris> tom@voyager.org', 'Tom Paris', 'tom@voyager.org'].toString()) {
    alert('測試失敗!');
}
else {
    alert('測試成功!');
}
相關文章
相關標籤/搜索