什么是 RegExp?
-
RegExp 是正則表達式(Regular expression)的縮寫,作用是對字符串執行模式匹配。
-
通常用於格式驗證、正則替換、查找子串等
-
各種編程語言的正則表達式基本相同,不同的語言可能會有一些細小的差別
-
完整的 RegExp 對象參考手冊:http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp
-
PHP 正則表達式:http://www.imooc.com/learn/350
-
javascript 正則表達式:http://www.imooc.com/learn/706
-
Python 正則表達式:http://www.imooc.com/learn/550
RegExp 語法
1
2
3
4
5
|
// 直接實例化
var reg = new RegExp(pattern [, flags]);
// 隱式創建(推薦)
var reg = /pattern/flags;
|
參數 pattern 是一個字符串,指定了正則表達式的模式或其他正則表達式。
參數 [, flags] 是一個可選的字符串,包含屬性 “g”(global )、”i” (ignoreCase)和 “m”(multiline)。
ECMAScript 標准化之前,不支持 m 屬性。如果 pattern 是正則表達式,而不是字符串,則必須省略該參數。

概念:子表達式
在正則表達式中,使用括號括起來的內容是一個子表達式,子表達式匹配到的內容會被系統捕獲至緩沖區,使用\n(n:數字)來反向引用系統的第n號緩沖區的內容。
場景:后面的內容要求與前面的一致,可以使用子表達式
1
2
3
4
5
|
// 查找連續相同的四個數字
var str = "1212ab45677778cd";
var reg = /(\d)\1\1\1/gi;
console.log(str.match(reg));
// OUTPUT:7777
|
概念:方括號(字符簇)
1
2
3
4
|
var str = "Is this all there is?";
var patt1 = /[a-h]/g;
document.write(str.match(patt1));
// OUTPUT:h,a,h,e,e
|
方括號 | 作用 |
---|---|
[abc] | 查找方括號之間的任何字符。 |
[^abc] | 查找任何不在方括號之間的字符。 |
[0-9] | 查找任何從 0 至 9 的數字。同 \d |
[a-z] | 查找任何從小寫 a 到小寫 z 的字符。 |
[A-Z] | 查找任何從大寫 A 到大寫 Z 的字符。 |
[A-z] | 查找任何從大寫 A 到小寫 z 的字符。 |
[0-9a-zA-Z] | 查找0-9,a-z,A-Z |
概念:元字符
元字符(Metacharacter)是擁有特殊含義的字符:
元字符 | 作用
—|—
\ | 轉義符 (、)、/、\
| | 選擇匹配符,可以匹配多個規則
. | 查找單個字符,除了換行和行結束符。
\w | 查找單詞字符。字符 ( 字母 ,數字,下划線_ )
\W | 查找非單詞字符。
\d | 查找數字。
\D | 查找非數字字符。
\s | 查找空白字符。空格
\S | 查找非空白字符。
\b | 匹配單詞邊界。
\B | 匹配非單詞邊界。
\0 | 查找 NUL 字符。
\n | 查找換行符。
\f | 查找換頁符。
\r | 查找回車符。
\t | 查找制表符。
\v | 查找垂直制表符。
\xxx | 查找以八進制數 xxx 規定的字符。
\xdd | 查找以十六進制數 dd 規定的字符。
\uxxxx | 查找以十六進制數 xxxx 規定的 Unicode 字符。
概念:量詞
量詞 | 作用 |
---|---|
n+ | 匹配任何包含至少一個 n 的字符串。同 {1,} |
n* | 匹配任何包含零個或多個 n 的字符串。同 {0,} |
n? | 匹配任何包含零個或一個 n 的字符串。同 {0,1} |
n{X} | 匹配包含 X 個 n 的序列的字符串。 |
n{X,Y} | 匹配包含 X 至 Y 個 n 的序列的字符串。 |
n{X,} | 匹配包含至少 X 個 n 的序列的字符串。 |
n$ | 匹配任何結尾為 n 的字符串。 |
^n | 匹配任何開頭為 n 的字符串。注意 /[^a] / 和 /^ [a]/是不一樣的,前者是排除的,后者是代表首位。 |
(?=n) | 匹配任何其后緊接指定字符串 n 的字符串。正向預查 |
(?!n) | 匹配任何其后沒有緊接指定字符串 n 的字符串。反向預查 |
RegExp 對象方法
test()
test() 方法檢索字符串中是否存在指定的值。返回值是 true 或 false。
1
2
3
4
5
6
7
|
var patt1 = new RegExp('e');
console.log(patt1.test('some text'));
// OUTPUT:true
var patt2 = new RegExp('ee');
console.log(patt2.test('some text'));
// OUTPUT:false
|
1
2
3
4
5
6
7
8
9
10
11
|
// 判斷是不是QQ號
// 1 首位不能是0 ^[1-9]
// 2 必須是 [5, 11] 位的數字 \d{4, 9}
var str = '80583600';
var regexp = /^[1-9][0-9]{4,10}$/gim;
if (regexp.test(str)) {
alert(
'is');
}
else {
alert(
'no');
}
|
exec()
exec() 方法檢索字符串中的指定值。返回值是被找到的值。如果沒有發現匹配,則返回 null。
1
2
3
4
5
6
7
|
var patt1 = new RegExp('e');
console.log(patt1.exec('some text'));
// OUTPUT:e
var patt2 = new RegExp('ee');
console.log(patt2.exec('some text'));
// OUTPUT:null
|
compile()
compile() 既可以改變檢索模式,也可以添加或刪除第二個參數。
1
2
3
4
5
6
|
var patt1=new RegExp("e");
document.write(patt1.test("The best things in life are free")); // true
// 改變了檢索模式
patt1.compile(
"eee");
document.write(patt1.test("The best things in life are free")); // false
|
支持正則表達式的 String 對象的方法
search 檢索與正則表達式相匹配的值。
1
2
3
|
var str = "Visit W3School!"
console.log(str.search(/W3School/))
// OUTPUT:6
|
match 找到一個或多個正則表達式的匹配。
1
2
3
|
var str="1 plus 2 equal 3"
console.log(str.match(/\d+/g))
// OUTPUT:1,2,3
|
replace 替換與正則表達式匹配的子串。
1
2
3
|
var str = "Visit Microsoft!"
console.log(str.replace(/Microsoft/, "W3School"));
// OUTPUT:Visit W3School!
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
// 找重復項最多的字符個數
var str = 'g21ss4aeba_ersb43sgnnsssstht6sss60snnsj8resw0_ss';
// split : 將字符串轉化為數組
// sort : 對數組排序,ASCII
// join : 將數組轉化為字符串
var str_new = str.split('').sort().join('');
document.write(str + '<br>');
document.write(str.split('') + '<br>');
document.write(str.split('').sort() + '<br>');
document.write(str.split('').sort().join('') + '<br>');
// 匹配字符,且重復這個字符,重復次數至少一次。
var regexp = /(\w)\1+/g;
var index = 0;
var value = '';
str_new.replace(regexp,
function($0, $1) {
// document.write($0);
// document.write($1);
if (index < $0.length) {
index = $
0.length;
value = $
1;
}
});
document.write('重復項最多的字符是:' + value + ',個數是:' + index);
// OUTPUT:
// 0012344668__aabbeeegghjnnnnrrssssssssssssssssttw
// 重復項最多的字符是:s,個數是:16
|
split 把字符串分割為字符串數組。
1
2
3
|
var str = "How are you doing today?"
document.write(str.split(/\s+/));
// OUTPUT:How,are,you,doing,today?
|
經驗:
- 檢驗格式(郵箱格式、IP格式)是否正確,用test()
- 抓取星期(如所有手機號),用exec()、match()
- 替換敏感詞匯,用replace()
常見的 正則表達式 校驗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
// 常見的 正則表達式 校驗
// QQ號、手機號、Email、是否是數字、去掉前后空格、是否存在中文、郵編、身份證、URL、日期格式、IP
var myRegExp = {
// 檢查字符串是否為合法QQ號碼
isQQ:
function(str) {
// 1 首位不能是0 ^[1-9]
// 2 必須是 [5, 11] 位的數字 \d{4, 9}
var reg = /^[1-9][0-9]{4,9}$/gim;
if (reg.test(str)) {
console.log('QQ號碼格式輸入正確');
return true;
}
else {
console.log('請輸入正確格式的QQ號碼');
return false;
}
},
// 檢查字符串是否為合法手機號碼
isPhone:
function(str) {
var reg = /^(0|86|17951)?(13[0-9]|15[012356789]|18[0-9]|14[57]|17[678])[0-9]{8}$/;
if (reg.test(str)) {
console.log('手機號碼格式輸入正確');
return true;
}
else {
console.log('請輸入正確格式的手機號碼');
return false;
}
},
// 檢查字符串是否為合法Email地址
isEmail:
function(str) {
var reg = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
// var reg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
if (reg.test(str)) {
console.log('Email格式輸入正確');
return true;
}
else {
console.log('請輸入正確格式的Email');
return false;
}
},
// 檢查字符串是否是數字
isNumber:
function(str) {
var reg = /^\d+$/;
if (reg.test(str)) {
console.log(str + '是數字');
return true;
}
else {
console.log(str + '不是數字');
return false;
}
},
// 去掉前后空格
trim:
function(str) {
var reg = /^\s+|\s+$/g;
return str.replace(reg, '');
},
// 檢查字符串是否存在中文
isChinese:
function(str) {
var reg = /[\u4e00-\u9fa5]/gm;
if (reg.test(str)) {
console.log(str + ' 中存在中文');
return true;
}
else {
console.log(str + ' 中不存在中文');
return false;
}
},
// 檢查字符串是否為合法郵政編碼
isPostcode:
function(str) {
// 起始數字不能為0,然后是5個數字 [1-9]\d{5}
var reg = /^[1-9]\d{5}$/g;
// var reg = /^[1-9]\d{5}(?!\d)$/;
if (reg.test(str)) {
console.log(str + ' 是合法的郵編格式');
return true;
}
else {
console.log(str + ' 是不合法的郵編格式');
return false;
}
},
// 檢查字符串是否為合法身份證號碼
isIDcard:
function(str) {
var reg = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;
if (reg.test(str)) {
console.log(str + ' 是合法的身份證號碼');
return true;
}
else {
console.log(str + ' 是不合法的身份證號碼');
return false;
}
},
// 檢查字符串是否為合法URL
isURL:
function(str) {
var reg = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i;
if (reg.test(str)) {
console.log(str + ' 是合法的URL');
return true;
}
else {
console.log(str + ' 是不合法的URL');
return false;
}
},
// 檢查字符串是否為合法日期格式 yyyy-mm-dd
isDate:
function(str) {
var reg = /^[1-2][0-9][0-9][0-9]-[0-1]{0,1}[0-9]-[0-3]{0,1}[0-9]$/;
if (reg.test(str)) {
console.log(str + ' 是合法的日期格式');
return true;
}
else {
console.log(str + ' 是不合法的日期格式,yyyy-mm-dd');
return false;
}
},
// 檢查字符串是否為合法IP地址
isIP:
function(str) {
// 1.1.1.1 四段 [0 , 255]
// 第一段不能為0
// 每個段不能以0開頭
//
// 本機IP: 58.50.120.18 湖北省荊州市 電信
var reg = /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/gi;
if (reg.test(str)) {
console.log(str + ' 是合法的IP地址');
return true;
}
else {
console.log(str + ' 是不合法的IP地址');
return false;
}
}
}
// 測試
// console.log(myRegExp.isQQ('80583600'));
// console.log(myRegExp.isPhone('17607160722'));
// console.log(myRegExp.isEmail('80583600@qq.com'));
// console.log(myRegExp.isNumber('100a'));
// console.log(myRegExp.trim(' 100 '));
// console.log(myRegExp.isChinese('baixiaoming'));
// console.log(myRegExp.isChinese('小明'));
// console.log(myRegExp.isPostcode('412345'));
// console.log(myRegExp.isIDcard('42091119940927001X'));
// console.log(myRegExp.isURL('https://www.baidu.com/'));
// console.log(myRegExp.isDate('2017-4-4'));
// console.log(myRegExp.isIP('1.0.0.0'));
|
一、校驗數字的表達式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
數字:^[0-9]*$
n位的數字:^\d{n}$
至少n位的數字:^\d{n,}$
m-n位的數字:^\d{m,n}$
零和非零開頭的數字:^(0|[1-9][0-9]*)$
非零開頭的最多帶兩位小數的數字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
帶1-2位小數的正數或負數:^(\-)?\d+(\.\d{1,2})?$
正數、負數、和小數:^(\-|\+)?\d+(\.\d+)?$
有兩位小數的正實數:^[0-9]+(.[0-9]{2})?$
有1~3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$
非零的正整數:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的負整數:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非負整數:^\d+$ 或 ^[1-9]\d*|0$
非正整數:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非負浮點數:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮點數:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮點數:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
負浮點數:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮點數:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
|
二、校驗字符的表達式
1
2
3
4
5
6
7
8
9
10
11
|
漢字:^[\u4e00-\u9fa5]{0,}$
英文和數字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
長度為3-20的所有字符:^.{3,20}$
由26個英文字母組成的字符串:^[A-Za-z]+$
由26個大寫英文字母組成的字符串:^[A-Z]+$
由26個小寫英文字母組成的字符串:^[a-z]+$
由數字和26個英文字母組成的字符串:^[A-Za-z0-9]+$
由數字、26個英文字母或者下划線組成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、數字包括下划線:^[\u4E00-\u9FA5A-Za-z0-9_]+$
可以輸入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止輸入含有~的字符:[^~\x22]+
|
三、特殊需求表達式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手機號碼:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
電話號碼("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
國內電話號碼(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
身份證號(15位、18位數字):^\d{15}|\d{18}$
短身份證號碼(數字、字母x結尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帳號是否合法(字母開頭,允許5-16字節,允許字母數字下划線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密碼(以字母開頭,長度在6~18之間,只能包含字母、數字和下划線):^[a-zA-Z]\w{5,17}$
強密碼(必須包含大小寫字母和數字的組合,不能使用特殊字符,長度在8-10之間):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12個月(01~09和1~12):^(0?[1-9]|1[0-2])$
一個月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正則表達式:[\u4e00-\u9fa5]
雙字節字符:[^\x00-\xff] (包括漢字在內,可以用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1))
空白行的正則表達式:\n\s*\r (可以用來刪除空白行)
HTML標記的正則表達式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (網上流傳的版本太糟糕,上面這個也僅僅能部分,對於復雜的嵌套標記依舊無能為力)
首尾空白字符的正則表達式:^\s*|\s*$或(^\s*)|(\s*$) (可以用來刪除行首行尾的空白字符(包括空格、制表符、換頁符等等),非常有用的表達式)
騰訊QQ號:[1-9][0-9]{4,} (騰訊QQ號從10000開始)
中國郵政編碼:[1-9]\d{5}(?!\d) (中國郵政編碼為6位數字)
IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址時有用)
IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
|
錢的輸入格式:
1
2
3
4
5
6
7
8
9
|
1.有四種錢的表示形式我們可以接受:"10000.00" 和 "10,000.00", 和沒有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
2.這表示任意一個不以0開頭的數字,但是,這也意味着一個字符"0"不通過,所以我們采用下面的形式:^(0|[1-9][0-9]*)$
3.一個0或者一個不以0開頭的數字.我們還可以允許開頭有一個負號:^(0|-?[1-9][0-9]*)$
4.這表示一個0或者一個可能為負的開頭不為0的數字.讓用戶以0開頭好了.把負號的也去掉,因為錢總不能是負的吧.下面我們要加的是說明可能的小數部分:^[0-9]+(.[0-9]+)?$
5.必須說明的是,小數點后面至少應該有1位數,所以"10."是不通過的,但是 "10" 和 "10.2" 是通過的:^[0-9]+(.[0-9]{2})?$
6.這樣我們規定小數點后面必須有兩位,如果你認為太苛刻了,可以這樣:^[0-9]+(.[0-9]{1,2})?$
7.這樣就允許用戶只寫一位小數.下面我們該考慮數字中的逗號了,我們可以這樣:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
8.1到3個數字,后面跟着任意個 逗號+3個數字,逗號成為可選,而不是必須:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
備注:這就是最終結果了,別忘了"+"可以用"*"替代如果你覺得空字符串也可以接受的話(奇怪,為什么?)最后,別忘了在用函數時去掉去掉那個反斜杠,一般的錯誤都在這里
|