javascript正则表达式—入门篇

写在前面:

(>﹏<)
正则表达式(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/
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容