写在前面:
(>﹏<)
正则表达式(Regular Expression)是一种用于模式匹配和替换的强大工具,由一系列普通字符和特殊字符组成。本文循序渐进介绍正则表达式的基本语法和应用,简单粗暴上代码,希望可以为正想学习它的小伙伴提供一点帮助,干货还请Google(°ο°)和查阅书籍。
学习正则表达式之前我们可以先复习一下传统的字符串操作:
- indexOf :查找字符的位置
- substring :获取子字符串
- charAt: 通过位置获取某个字符串
- split :分割字符串,获得数组
……
热身小例子copy代码运行一下(╯▽╰) !
:
找出字符串中所有的数字 !
-- 用传统字符串操作完成:
<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>
看到这,正则表达式的好处不言而喻,方便且高性能。
下面进入正题:
如何创建正则表达式(RegExp对象):
简写: 字面量:var re = /匹配对象的模式/;
注意:为了使双斜杠不被浏览器当成注释,随便写点东西使它不为空,但里面不一定都是字符串哦,所以不要加引号。
全称: 构造函数:var re = new RegExp(匹配对象的模式,修饰符);
RegExp()构造函数带有两个参数,都是字符串,第一个是正则表达式,第二个是修饰符,第二个参数是可选的,注意,当RegExp()传入一个字符串表述的正则表达式时,要把 "" 替换成 "\",不能把正则表达式字面量直接传给RegExp()。
比如:var re = new RegExp( "\\{d}","g") 匹配5个数字,用的是\\不是\。
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
//执行结果不全是数字
var str2 = '374829r348791';
var re = /\D/;
if( re.test(str2) ){
alert('不全是数字');
}
else{
alert('全是数字');
}
</script>
2.exec()
exec() 方法用于检索字符串中的正则表达式的匹配。
语法:rgExp.exec(str)
如果字符串中有匹配的值返回该匹配值,否则返回 null。
exec()还包括index和input两个属性。input就是str的值,index是匹配项在字符串中的位置。
exec()方法是专门为捕获组设计的(就是子项)。
<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()方法如果不设置全局标志g,每次返回一个匹配项,多次调用exec()方法也会始终返回第一个匹配项;
而如果exec()方法设置了全局标志g,虽然每次还是只返回一个匹配项,但是每次再调用时都会在字符串中继续往下寻找新的匹配项:
<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() 方法用于在脚本执行过程中编译正则表达式。
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()
正则匹配字符串,如果匹配成功,就返回匹配成功的第一个子字符串的位置(整数值);如果匹配失败返回-1。
注意:search()方法不支持全局搜索,因为他会忽略正则表达式中的修饰符g
语法:stringObj.search(rgExp)
说明:stringObj是要在其上进行查找的对象,rgExp正则表达式模式
注意:正则中默认区分大小写,如果不想区分大小写,在正则的最后加上表示“i”。
<script>
var str = 'abcdef';
var re0 = /B/;
var re1 = /B/i;
// 完整写法,i放在第二个参数上,引号引上
// var re1 = new RegExp( 'B','i' );
var re2 = /a/;
var re3 = /ab/;
alert( str.search(re0) ); //找不到返回-1
alert( str.search(re1) ); //不区分大小写,找得到,返回1
alert( str.search(re2) ); //返回0
alert( str.search(re3) ); //返回0
</script>
2.match()
即热身例子里的方法.
使用正则在字符串中进行查找匹配,如果匹配成功,返回匹配成功的数组;如果匹配失败则返回null;
语法:stringObj.match( rgExp )
说明:stringObj是要在其上进行查找的对象,rgExp正则表达式模式
注意:使用match()方法时,正则表达式默认匹配成功就会结束,不会继续匹配; 如果想全部查找就要加全局匹配标示“g”。
\d 只代表一位数字,所以相连数字在数组中不会连成一项,\d\d 代表两位数字。这里简单介绍量词 “ + ”,“ + ”代表+前面的字符出现不确定的次数(1~n,至少一次),所以 \d+ 代表相连的不确定个数的数字。
<script>
var str = 'haj123sdk54hask33dkhalsd879';
str.match( /\d/); //数组 [ 1 ]
str.match( /\d/g ); //数组 [ 1,2,3,4,5,3,3,8,7,9 ]
str.match( /\d\d/g ); //数组 [12,54,33,87 ]
str.match( /\d+/g ); //数组 [ 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()
使用正则表达式对字符串搜索,用指定的字符串替换搜索到的内容,返回替换后的字符串对象。
语法:字符串.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艘中国船均在菲军监视之下
//| : 或的意思
//replace : 第二个参数:可以是字符串,也可以是一个回调函数
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,function(str){
//函数的第一个参数:就是匹配成功的字符
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){
//第一个参数:$0(母亲),第二个参数 : $1(第一个孩子)
//,第二个参数 : $1(第二个孩子)
return $1 + '.';
});
alert( str ); //2013.6.7
</script>
4.split()
返回按照某种分割标志将一个字符拆分成若干个子字符串时所产生的字符串数组。
分割标志即split的参数可以是字符也可以是正则表达式。
语法:split(separator[,limit])
separator是分割标志参数,limit限制返回元素的个数。
例如:
"123,456,789".split(",");
//返回数组[ "123", "456", "789" ]
"1, 2, 3, 4, 5".split("\s*,\s*");
//指定分隔符,两边可以有若干留白,返回数组[ "1", "2", "3", "4", "5" ]
正则表达式的字符类
大写的都是非字开头,小写的是逆运算,方便记忆。
字符 | 匹配 |
---|---|
[ ... ] | 方括号内的任意字符 |
[ ^...] | 不包括方括号内的任意字符 |
. | 除换行符和其他unicode行终止符之外的任意字符 |
\s | 空白Unicode字符 |
\S | 非Unicode空白字符 |
\d | 数字 |
\D | 非数字 |
\w | 字符(数字、字母、下划线) |
\W | 非字符 (除数字、字母、下划线以外的字符) |
[\b] | 退格直接量 |
正则表达式修饰符:
i:执行不分大小写的匹配
g:执行一个全局匹配,找到所有匹配,不在找到第一个之后就停止
m:多行匹配模式 ^匹配一行或字符串的开头,$匹配行或字符串的结束
任意字符 : 一组相似的元素 , [ ] 中括号的整体代表一个字符
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之间是或的关系,整体代表一位
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>
转义字符
比如:
. : 任意字符 . : 真正的点
\d \w \s \b
\D \W \S \B
\1 (没错,你没看错这个是数字 1 ,除了1还可能是其他数字)
\b用法:
<script>
var str1 = 'a.c';
var re1 = /a\.c/;
alert(re1.test(str1)); //true
//\b : 独立的部分 ( \b后面是起始,结束,空格 )
//\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>
具体会在什么地方有用呢?看下面这个, “\数字” 的写法是不仅类型一样,而且值也要一样。例如在选取<div></div>等标签时会用到
var re = /\w\w/; // 可以匹配xy
var re = /(\w)\1/; // 可以匹配xx 、yy , 但不可以匹配xy
例子(可能在面试中出现):
找重复项最多的字符和个数:
<!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+',重复的次数:'+index);
</script>
</head>
<body>
</body>
</html>
!!注意:正则表达式选择项的尝试匹配次序是从左到右,直到发现了匹配项。如果左边的选择项匹配了,就忽略右边的,即使能产生更好的匹配,
例如:
/a|ab/匹配字符串ab时,只能匹配第一个字符a。
<script type="text/javascript">
var text = "ab";
var pattern1 = /a|ab/;
alert( text.match(pattern1) ); //a
</script>
量词:{ }
重复字符语法:表示出现次数, 注意该类符号匹配前一项。
- { n, m } 至少出现n次,最多出现m次
- { n } 正好出现n次
- { 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号
^ : 正则的最开始位置,代表起始(^在[ ]外面和里面表示的意思是不一样的)
$ : 正则的最后位置 , 代表结束
<!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}$
- 网址:[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
########实际开发注意事项:
可以把这些正则表达式包在一个空间里,有人叫做命名空间。
(JSON的使用:json就是javascript中的数组和对象。)
var re = {
qq: /^[1-9]\d{4,11}$/,
email: /^\w+@[a-z0-9]+(\.[a-z]+){1,3}$/,
number:/\d/
}