寫在前面:
(>﹏<)
正則表達式(Regular Expression)是一種用于模式匹配和替換的強大工具,由一系列普通字符和特殊字符組成。本文循序漸進介紹正則表達式的基本語法和應(yīng)用,簡單粗暴上代碼,希望可以為正想學習它的小伙伴提供一點幫助,干貨還請Google(°ο°)和查閱書籍。
學習正則表達式之前我們可以先復習一下傳統(tǒng)的字符串操作:
- indexOf :查找字符的位置
- substring :獲取子字符串
- charAt: 通過位置獲取某個字符串
- split :分割字符串,獲得數(shù)組
……
熱身小例子copy代碼運行一下(╯▽╰) !:
找出字符串中所有的數(shù)字 !
-- 用傳統(tǒng)字符串操作完成:
<script>
var str = 'haj123sdk54hask33dkhalsd879';
function findNum (str) {
var arr = [];
var temp = '';
for ( var i = 0; i < str.length; i++ ) {
var num = str.charAt(i);
if ( num <= '9' && num >= '0' ) {
temp += num;
}else {
if ( temp ) {
arr.push(temp);
temp = '';
}
}
}
if ( temp ) {
arr.push(temp);
temp = '';
}
return arr;
}
alert( findNum(str) );
</script>

-- 用正則表達式完成
<script>
var str = 'haj123sdk54hask33dkhalsd879';
function findNum (str) {
return str.match( /\d+/g );
}
alert( findNum(str) );
</script>

看到這,正則表達式的好處不言而喻,方便且高性能。
下面進入正題:
如何創(chuàng)建正則表達式(RegExp對象):
簡寫: 字面量:var re = /匹配對象的模式/;
注意:為了使雙斜杠不被瀏覽器當成注釋,隨便寫點東西使它不為空,但里面不一定都是字符串哦,所以不要加引號。
全稱: 構(gòu)造函數(shù):var re = new RegExp(匹配對象的模式,修飾符);
RegExp()構(gòu)造函數(shù)帶有兩個參數(shù),都是字符串,第一個是正則表達式,第二個是修飾符,第二個參數(shù)是可選的,注意,當RegExp()傳入一個字符串表述的正則表達式時,要把 "" 替換成 "\",不能把正則表達式字面量直接傳給RegExp()。
比如:var re = new RegExp( "\\u0z1t8os","g") 匹配5個數(shù)字,用的是\\不是\。
RegExp對象方法:
1.test()
返回一個布爾值,正則去匹配字符串,如果匹配成功返回true,如果匹配失敗返回false
語法:rgexp.test(str)
說明:rgexp代表正則表達式,str代表要查找字符串
<script>
var str = 'abcefg';
var re1 = /b/;
var re2 = /ab/;
var re3 = /ac/;
var re4 = /w/;
alert ( re1.test(str)); //返回true
alert ( re2.test(str)); //返回true
alert ( re3.test(str)); //返回false
alert ( re4.test(str)); //返回false
//執(zhí)行結(jié)果不全是數(shù)字
var str2 = '374829r348791';
var re = /\D/;
if( re.test(str2) ){
alert('不全是數(shù)字');
}
else{
alert('全是數(shù)字');
}
</script>
2.exec()
exec() 方法用于檢索字符串中的正則表達式的匹配。
語法:rgExp.exec(str)
如果字符串中有匹配的值返回該匹配值,否則返回 null。
exec()還包括index和input兩個屬性。input就是str的值,index是匹配項在字符串中的位置。
exec()方法是專門為捕獲組設(shè)計的(就是子項)。
<script type="text/javascript">
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
alert(matches.index); //0
alert(matches.input); //"mom and dad and baby"
alert(matches[0]); //"mom and dad and baby"
alert(matches[1]); //" and dad and baby"
alert(matches[2]); //" and baby"
</script>
exec()方法如果不設(shè)置全局標志g,每次返回一個匹配項,多次調(diào)用exec()方法也會始終返回第一個匹配項;
而如果exec()方法設(shè)置了全局標志g,雖然每次還是只返回一個匹配項,但是每次再調(diào)用時都會在字符串中繼續(xù)往下尋找新的匹配項:
<script type="text/javascript">
var text = "cat, bat, sat, fat";
var pattern1 = /.at/;
var matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern1.lastIndex);//0
matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern1.lastIndex);//0
var pattern2 = /.at/g;
var matches = pattern2.exec(text);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern2.lastIndex);//0
matches = pattern2.exec(text);
alert(matches.index); //5
alert(matches[0]); //"bat"
alert(pattern2.lastIndex);//0
</script>
3.compile()
語法:RegObject.compile(正則表達式,修飾符)
compile() 方法用于在腳本執(zhí)行過程中編譯正則表達式。
compile() 方法也可用于改變和重新編譯正則表達式。
例子:在字符串中全局搜索 "man",并用 "person" 替換。然后通過 compile() 方法,改變正則表達式,用 "person" 替換 "man" 或 "woman",:
<script type="text/javascript">
var str="Every man in the world! Every woman on earth!";
patt=/man/g;
str2=str.replace(patt,"person");
document.write(str2+"<br />");
patt=/(wo)?man/g;
patt.compile(patt);
str2=str.replace(patt,"person");
document.write(str2);
</script>
輸出:
Every person in the world! Every woperson on earth!
Every person in the world! Every person on earth!
支持正則表達式的 String 對象的方法
1.search()
正則匹配字符串,如果匹配成功,就返回匹配成功的第一個子字符串的位置(整數(shù)值);如果匹配失敗返回-1。
注意:search()方法不支持全局搜索,因為他會忽略正則表達式中的修飾符g
語法:stringObj.search(rgExp)
說明:stringObj是要在其上進行查找的對象,rgExp正則表達式模式
注意:正則中默認區(qū)分大小寫,如果不想?yún)^(qū)分大小寫,在正則的最后加上表示“i”。
<script>
var str = 'abcdef';
var re0 = /B/;
var re1 = /B/i;
// 完整寫法,i放在第二個參數(shù)上,引號引上
// var re1 = new RegExp( 'B','i' );
var re2 = /a/;
var re3 = /ab/;
alert( str.search(re0) ); //找不到返回-1
alert( str.search(re1) ); //不區(qū)分大小寫,找得到,返回1
alert( str.search(re2) ); //返回0
alert( str.search(re3) ); //返回0
</script>
2.match()
即熱身例子里的方法.
使用正則在字符串中進行查找匹配,如果匹配成功,返回匹配成功的數(shù)組;如果匹配失敗則返回null;
語法:stringObj.match( rgExp )
說明:stringObj是要在其上進行查找的對象,rgExp正則表達式模式
注意:使用match()方法時,正則表達式默認匹配成功就會結(jié)束,不會繼續(xù)匹配; 如果想全部查找就要加全局匹配標示“g”。
\d 只代表一位數(shù)字,所以相連數(shù)字在數(shù)組中不會連成一項,\d\d 代表兩位數(shù)字。這里簡單介紹量詞 “ + ”,“ + ”代表+前面的字符出現(xiàn)不確定的次數(shù)(1~n,至少一次),所以 \d+ 代表相連的不確定個數(shù)的數(shù)字。
<script>
var str = 'haj123sdk54hask33dkhalsd879';
str.match( /\d/); //數(shù)組 [ 1 ]
str.match( /\d/g ); //數(shù)組 [ 1,2,3,4,5,3,3,8,7,9 ]
str.match( /\d\d/g ); //數(shù)組 [12,54,33,87 ]
str.match( /\d+/g ); //數(shù)組 [ 123, 54, 33, 879 ]
</script>
例子:
<script>
var str = 'abc';
var re = /(a)(b)(c)/;
alert( str.match(re) ); //[abc,a,b,c](當正則不加g的時候才可以獲取到子項的集合)
</script>
3.replace()
使用正則表達式對字符串搜索,用指定的字符串替換搜索到的內(nèi)容,返回替換后的字符串對象。
語法:字符串.replace(正則表達式,新的字符串)
<script>
var str = 'aaa';
var re1 = /a+/g;
var re2 = /a/g;
var re3 = /a/;
str1 = str.replace(re1,'b');
str2 = str.replace(re2,'b');
str3 = str.replace(re3,'b');
alert(str1); // 返回b
alert(str2); // 返回bbb
alert(str3); // 返回baa
</script>
例子1:替換
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<script>
//菲稱仁愛礁附近17艘中國船均在菲軍監(jiān)視之下
//| : 或的意思
//replace : 第二個參數(shù):可以是字符串,也可以是一個回調(diào)函數(shù)
window.onload = function(){
var aT = document.getElementsByTagName('textarea');
var oInput = document.getElementById('input1');
var re = /菲稱|中國船|監(jiān)視之下/g;
oInput.onclick = function(){
aT[1].value = aT[0].value.replace(re,function(str){
//函數(shù)的第一個參數(shù):就是匹配成功的字符
var result = '';
for(var i=0;i<str.length;i++){
result += '*';
}
return result;
});
};
};
</script>
</head>
<body>
替換前<br />
<textarea>
</textarea><br />
替換后<br />
<textarea>
</textarea><br />
<input type="button" value="確定" id="input1" />
</body>
</html>

例子2:匹配子項
匹配子項 : 小括號 () (還有另外一個作用,分組操作)
<script>
//1+1*2
//(1+1)*2
//把正則的整體叫做(母親)
//然后把左邊第一個小括號里面的正則,叫做這個第一個子項(母親的第一個孩子),也叫捕獲組
//第二個小括號就是第二個孩子
var str = '2013-6-7';
var re = /(\d+)(-)/g;
str = str.replace(re,function($0,$1,$2){
//第一個參數(shù):$0(母親),第二個參數(shù) : $1(第一個孩子)
//,第二個參數(shù) : $1(第二個孩子)
return $1 + '.';
});
alert( str ); //2013.6.7
</script>
4.split()
返回按照某種分割標志將一個字符拆分成若干個子字符串時所產(chǎn)生的字符串數(shù)組。
分割標志即split的參數(shù)可以是字符也可以是正則表達式。
語法:split(separator[,limit])
separator是分割標志參數(shù),limit限制返回元素的個數(shù)。
例如:
"123,456,789".split(",");//返回數(shù)組[ "123", "456", "789" ]
"1, 2, 3, 4, 5".split("\s*,\s*"); //指定分隔符,兩邊可以有若干留白,返回數(shù)組[ "1", "2", "3", "4", "5" ]
正則表達式的字符類
大寫的都是非字開頭,小寫的是逆運算,方便記憶。
| 字符 | 匹配 |
|---|---|
| [ ... ] | 方括號內(nèi)的任意字符 |
| [ ^...] | 不包括方括號內(nèi)的任意字符 |
| . | 除換行符和其他unicode行終止符之外的任意字符 |
| \s | 空白Unicode字符 |
| \S | 非Unicode空白字符 |
| \d | 數(shù)字 |
| \D | 非數(shù)字 |
| \w | 字符(數(shù)字、字母、下劃線) |
| \W | 非字符 (除數(shù)字、字母、下劃線以外的字符) |
| [\b] | 退格直接量 |
正則表達式修飾符:
i:執(zhí)行不分大小寫的匹配
g:執(zhí)行一個全局匹配,找到所有匹配,不在找到第一個之后就停止
m:多行匹配模式 ^匹配一行或字符串的開頭,$匹配行或字符串的結(jié)束
任意字符 : 一組相似的元素 , [ ] 中括號的整體代表一個字符
var str1 = 'abc';
var str2 = 'abdc';
var re= /a[bde]c/;
alert( re.test(str1) ); //true
alert( re.test(str2) ); //false
排除:^符號。 如果^寫在[ ]里面的話,就代表排除的意思
var str1 = 'abc';
var str2 = 'awc';
var re = /a[^bde]c/;
alert( re.test(str1) ); //false
alert( re.test(str2) ); //true
范圍:從小到大
var str = 'abc';
var re = /a[a-z0-9A-Z]c/; //a-z 0-9 A-Z之間是或的關(guān)系,整體代表一位
alert( re.test(str) ); //true
例子:過濾標簽
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<script>
window.onload = function(){
var aT = document.getElementsByTagName('textarea');
var oInput = document.getElementById('input1');
var re = /<[^>]+>/g;
oInput.onclick = function(){
aT[1].value = aT[0].value.replace(re,'');
};
};
</script>
</head>
<body>
替換前<br />
<textarea>
</textarea><br />
替換后<br />
<textarea>
</textarea><br />
<input type="button" value="確定" id="input1" />
</body>
</html>

轉(zhuǎn)義字符
比如:
. : 任意字符 . : 真正的點
\d \w \s \b
\D \W \S \B
\1 (沒錯,你沒看錯這個是數(shù)字 1 ,除了1還可能是其他數(shù)字)
\b用法:
<script>
var str1 = 'a.c';
var re1 = /a\.c/;
alert(re1.test(str1)); //true
//\b : 獨立的部分 ( \b后面是起始,結(jié)束,空格 )
//\B : 非獨立的部分
var str2 = 'onetwo';
var re2 = /one\b/;
alert( re2.test(str2) ); //false
</script>
例子:利用\b獲取class方法
注意:當正則表達式需要傳參的時候,一定要用全稱的寫法!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<script>
window.onload = function(){
var aLi = getByClass(document,'box1');
for(var i=0;i<aLi.length;i++){
aLi[i].style.background = 'red';
}
function getByClass(oParent,sClass){
var arr = [];
var aEle = oParent.getElementsByTagName('*');
//var re = /sClass/; //簡寫不可以,當正則需要傳參的時候,一定要用全稱的寫法
var re = new RegExp('\\b'+sClass+'\\b');
for(var i=0;i<aEle.length;i++){
if( re.test(aEle[i].className) ){
arr.push( aEle[i] );
}
}
return arr;
}
};
</script>
</head>
<body>
<ul>
<li class="box1">111</li>
<li>111</li>
<li class="box1box2">111</li>
<li>111</li>
<li class="box1 box2">111</li>
</ul>
</body>
</html>

重復子項:
\1 : 代表重復的第一個子項
\2 : 代表重復的第二個子項
<script>
//\1 : 代表重復的第一個子項
//\2 : 代表重復的第二個子項
var str = 'abca';
var re = /(a)(b)(c)\1/;
alert( re.test(str) ); //true
</script>
具體會在什么地方有用呢?看下面這個, “\數(shù)字” 的寫法是不僅類型一樣,而且值也要一樣。例如在選取<div></div>等標簽時會用到
var re = /\w\w/; // 可以匹配xy
var re = /(\w)\1/; // 可以匹配xx 、yy , 但不可以匹配xy
例子(可能在面試中出現(xiàn)):
找重復項最多的字符和個數(shù):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<script>
var str = 'assssjdssskssalsssdkjsssdss';
var arr = str.split('');
str = arr.sort().join('');
//alert(str); aadddjjkklsssssssssssssssss
var value = '';
var index = 0;
var re = /(\w)\1+/g;
str.replace(re,function($0,$1){
//alert($0);
if(index<$0.length){
index = $0.length;
value = $1;
}
});
alert('最多的字符:'+value+',重復的次數(shù):'+index);
</script>
</head>
<body>
</body>
</html>

??!注意:正則表達式選擇項的嘗試匹配次序是從左到右,直到發(fā)現(xiàn)了匹配項。如果左邊的選擇項匹配了,就忽略右邊的,即使能產(chǎn)生更好的匹配,
例如:
/a|ab/匹配字符串a(chǎn)b時,只能匹配第一個字符a。
<script type="text/javascript">
var text = "ab";
var pattern1 = /a|ab/;
alert( text.match(pattern1) ); //a
</script>
量詞:{ }
重復字符語法:表示出現(xiàn)次數(shù), 注意該類符號匹配前一項。
- { n, m } 至少出現(xiàn)n次,最多出現(xiàn)m次
- { n } 正好出現(xiàn)n次
- { n, } 至少出現(xiàn)n次 ( ≥n )
- * : { 0, } 任意次, 即至少0次 ( ≥0 )
- ?: { 0,1 } 0次或1次 ( 就是說前一項是可選的 )
- + : { 1, } 1次或任意次 ( ≥1 )
var str1 = 'ac';
var str2 = 'ab';
var re1 = /ab*/;
var re2 = /ab+/;
alert(re1.test(str1)); //true
alert(re2.test(str2)); //true
例子1:判斷是否是QQ號
^ : 正則的最開始位置,代表起始(^在[ ]外面和里面表示的意思是不一樣的)
$ : 正則的最后位置 , 代表結(jié)束
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<script>
window.onload = function(){
var aInput = document.getElementsByTagName('input');
var re = /^[1-9]\d{4,11}$/;
aInput[1].onclick = function(){
if( re.test(aInput[0].value) ){
alert('是QQ號');
}
else{
alert('不是QQ號');
}
};
};
</script>
</head>
<body>
<input type="text" /><input type="button" value="確定" />
</body>
</html>

例子2:去掉首尾空格
<script>
var str = ' hello ';
alert( '('+trim(str)+')' );
function trim(str){
var re = /^\s+|\s+$/g;
return str.replace(re,'');
}
</script>

高級表單校驗,僅供參考
- 匹配中文:[\u4e00-\u9fa5]
- 行首行尾空格:^\s|\s$
- Email:^\w+@[a-z0-9]+(.[a-z]+){1,3}$
- 網(wǎng)址:[a-zA-z]+://[^\s]*
- QQ號:^[1-9]\d{4,11}$
- 郵政編碼:[1-9]\d{5}
- 身份證:[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x
########實際開發(fā)注意事項:
可以把這些正則表達式包在一個空間里,有人叫做命名空間。
(JSON的使用:json就是javascript中的數(shù)組和對象。)
var re = {
qq: /^[1-9]\d{4,11}$/,
email: /^\w+@[a-z0-9]+(\.[a-z]+){1,3}$/,
number:/\d/
}