一、基本概念 和 定義
用一種描述性的語言來給字符串定義一個規則,你能夠形象地理解正則表達式是一個「框」,凡是符合大小形狀條件的字符串,都算是「匹配「了。
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('測試成功!');
}