JavaScript中的正则表达式(终结篇)
在之前的几篇文章中,我们了解了正则表达式的基本语法,但那些语法不是针对于某一个特定语言的。这篇博文我们将通过下面几个部分来了解正则表达式在JavaScript中的使用:
第一部分:JavaScript对正则表达式的支持程度
之前我介绍了正则表达式的基本语法,如果大家不是很了解可以先看下面几篇文章:
但是ECMAScript并没有支持上述正则表达式的所有功能,尤其是缺少一些语言所支持的高级正则表达式特性。下面的这些都是JavaScript所不支持的:
- 匹配字符串开始和结尾的\A和\Z锚。(但我们仍可以使用^和$来匹配字符串的开始和结尾)
- 向后查找(lookbehind)(注:但是JavaScript完全支持向前查找(lookahead))
- 并集和交集类
- 原子组(atomic grouping)
- Unicode支持(单个字符除外,如\uFFFF)
- 命名的捕获组
- s(single,单行)和x(free-spacing,无间隔)匹配模式
- 条件匹配
- 正则表达式注释
更多关于JavaScript对正则表达式支持的内容可以点击这里。
第二部分:支持正则表达式的RegExp类型
JavaScript是通过RegExp类型来支持正则表达式的。而创建RegExp类型有两种方法。一种是字面量方法(类似于Perl的语法),另一种是使用JavaScript的RegExp构造函数,下面将逐一介绍。
1.字面量方法
var expression = /pattern/flags;
其中expression即为正则表达式的名称,模式(pattern)可以是任何复杂或简单的正则表达式(但必须是在JavaScript支持范围内的),标志(flags)即用来表明正则表达式行为。
下面介绍JavaScript中支持的三个标志(flags):
- g: 表示全局(global)模式,表示pattern会应用于所有字符串,而不是找到一个匹配项后立即停止。
- i :表示不区分大小写(ignore)模式。即忽略pattern和字符串的大小写。
- m:表示多行(multiple)模式。 即到一行文本末尾时还会继续查找下一行中是否存在匹配的项。
说明:在字面量方法中的flags可以是g、i、m中的任意一个或几个且这里的标志完全适用于之后要讲的RegExp构造函数方法。
举例:
var pattern=/at/gi;
此字面量形式的正则表达式表示在不区分大小写的情况下在全局范围内匹配at。
2.RegExp构造函数法
var pattern = new RegExp("pattern","flags");
即这种方法使用了RegExp构造函数,并且传递了两个参数(同字面量方法),但值得注意的是:pattern(模式)和flags(标志)都需要使用引号括起来。
3.对模式中的元字符转义的方法
当我们希望使用元字符本身的含义时,我们就需要对元字符进行转义。比如[ab]c表示ac或bc;若通过\转义,即\[ab\]c就表示成了[ab]c。但是对于上述两种不同的创建方法有不同的转义方式。
首先,请记住在JavaScript中的元字符有 ( [ { \ ^ $ | ) ? * + . ] ) }。
使用字面量方法创建正则表达式转义:在需要转义的正则表达式前加\即可。如var pattern = /\[ab\]c/g;表示在全局范围内匹配abc
使用RegExp构造函数创建正则表达式转义:在需要转义的正则表达式前加\\。如var pattern = RegExp("\\[ab\\]c","g");同样表示在全局范围内匹配abc
4.举例
如果希望知道字符串XxxxoOoooommmm中o的数量(不区分大小写),这时就可以使用match方法传入字符串,如:
var string = "XxxxoOoooommmm"; console.log(string.match(/o/ig).length);
输出为6,这种方法还是很容易的。
第三部分:RegExp的实例属性
无论是何种方法创建的正则表达式,他们都具有下面几种属性来描述有关模式的信息:
- global---表示flags(标志)中是否设置了g标志。
- ignoreCase---表示flags(标志)中是否设置了i标志。
- lastIndex---表示开始搜索下一个匹配项的字符位置的整数,从0算起。
- multiple---表示flags(标志)中是否设置了m标志。
- source---按照字面量形式返回正则表达式的字符串表示。
举例如下所示:
// var pattern = RegExp("\\[ba\\]at","gi");//使用RegExp构造函数创建得到的效果和下面使用的字面量方法创建得到的效果相同 var pattern = /\[ba\]at/gi; console.log(pattern.global); //true console.log(pattern.ignoreCase); //true console.log(pattern.multiline); //ture console.log(pattern.lastIndex); //0 console.log(pattern.source); // \[ba\]at
当然,上面代码中使用了大量的console.log()显得很复杂,也可以将这5个属性作为5个参数直接传入到console.log()中。如下所示:
var pattern = /\[ba\]at/gi; console.log(pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source); //true true false 0 "\[ba\]at"
我们还可以将这5个属性保存在一个数组中,再通过console.log()直接输出数组,如下所示:
var pattern = /\[ba\]at/gi; var properties=[pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source]; console.log(properties);
在控制台中可以看到:
第四部分:RegExp的实例方法
RegExp的实例主要有两个方法exec()和test(),并且还有从Object继承的toString()和toLocaleString()方法,下面将会逐一介绍。
1.RegExp实例的exec()方法
这个方法接收一个参数,即要应用模式的字符串,用于捕获组。
如果匹配,则返回一个数组;否则返回null。
且其中返回的数组还有额外的两个方法:index和input。index表示匹配项在字符串中的位置,input表示应用正则表达式的字符串。
举例如下所示:
var text="mom and dad and baby"; var pattern=/mom( and dad( and baby)?)?/gi; var matches=pattern.exec(text); console.log(matches);
如果匹配不了,则matches为null;如果匹配,将会在控制台中输出一个数组,如下所示:
我们可以看到,数组中包含三个元素,分别是matches[0]、matches[1]和matches[2]。并且在数组中还有一个index属性为0,表示匹配项在字符串中的位置为0,即在开始处就匹配上了。 而input属性是text字符串。
2.RegExp实例的test()方法
这个方法同样也接收一个字符串,如果pattern(模式)和字符串匹配,则返回true,否则返回false。
并且test()方法经常被用在if语句中,举例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Regular Expression</title> </head> <body> <input type="text" id="phoneNumber"> <button id="submit">提交</button> <script> window.onload=function(){ var btn=document.getElementById("submit"); btn.onclick=function(){ var phoneNumber=document.getElementById("phoneNumber").value; var pattern=/1[358]\d{9}/gi; if(pattern.test(phoneNumber)){ alert("Yes! Your phoneNumber is legal"); }else{ alert("No!Your phoneNumber is illegal"); } } } </script> </body> </html>
这个小demo可以判断用户输入的手机号码是否合法,并给出响应提示,演示如下:
3.RegExp实例的toString()和toLocalString()方法
这两个方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。
举例如下:
var pattern=/1[358]\d{9}/gi; console.log(pattern.toString()); console.log(pattern.toLocaleString());
在控制台中我们可以看到效果如下所示:
第五部分:RegExp的构造函数属性
RegExp构造函数也包含了一些属性。值得注意的是,这些属性有两种方式来访问---长属性名和短属性名。介绍如下:
- input $_ 最近一次要匹配的字符串 。(注意:前者是长属性名,后者是短属性名,下同)
- lastMatch $& 最近一次的匹配向。
- lastParen $+ 最近一次匹配的捕获组。
- leftContext $` input字符串中lastMatch之前的文本
- RightContext $' input字符串中lastMatch之后的文本
- multiline $* 布尔值,表示是否所有表达式都使用多行模式
注意:Opera不支持上面的1236对应的四个属性,IE不支持multiline属性。
举例如下所示:
var text="this has been a short summer"; var pattern=/(.)hort/g; if(pattern.test(text)){ console.log(RegExp.input);//this has been a short summer console.log(RegExp.leftContext);//this has been a console.log(RegExp.rightContext);//summer console.log(RegExp.lastParen);//s console.log(RegExp.lastMatch);//short console.log(RegExp.multiline);//undefined }
第六部分:简单的应用
1.用户名和密码验证
需求如下:
- 用户名输入:必须为长度在5~20之间的英文字母,否则提交后报错。
- 密码输入:必须是数字和字母结合,且长度必须为8,否则提交后报错。
实现思路:
- 用户名和密码是否同时正确,正确显示“成功”。
- 用户名错误,密码正确,则显示“用户名有误,请重新输入...”
- 用户名正确,密码错误,则显示“密码有误,请重新输入...”
- 用户名和密码都错误,则显示“用户名和密码均输入有误!!!”
代码如下所示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Regular Expression</title> <style> input{box-sizing: border-box;padding:10px;width: 300px;height: 50px;line-height: 50px;} input[type="submit"]{height: 30px;line-height: 30px;padding:0;} </style> </head> <body> <form action=""> <input type="text" id="username" placeholder="请输入长度在5~20之前的英文名称..." ><br> <input type="password" id="password" placeholder="请输入长度为8的数字和英文组成的密码..."><br> <input type="submit" id="submit" value="提交"> </form> <script> window.onload=function(){ var btn=document.getElementById("submit"); btn.onclick=function(){ event.preventDefault(); var username=document.getElementById("username"); var password=document.getElementById("password"); var usernamePattern=/[a-zA-Z]{5,20}/g; var passwordPattern=/[\da-zA-Z]*((\d+[a-zA-Z]+)|([a-zA-Z]+\d+))[\da-zA-Z]*/g; if(usernamePattern.test(username.value)&&(passwordPattern.test(password.value)&&(password.value.length==8))){ alert("成功!"); }else if((!usernamePattern.test(username.value))&&(passwordPattern.test(password.value)&&(password.value.length==8))){ alert("用户名输入有误!请重新输入..."); }else if((!(passwordPattern.test(password.value)&&(password.value.length==8)))&&usernamePattern.test(username.value)){ alert("密码输入有误!请重新输入..."); }else{ alert("用户名和密码均输入有误!!!"); } } }; </script> </body> </html>
关键在于判断输入的准确与否,这里我使用的是与运算。如当密码输入正确,用户名错误时在用户名的判断代码前取非即可,其他同理。
效果如下:
ok,这篇博文就到这里啦,如果觉得不错,就推荐一下吧!
第七部分:需要注意的地方
1. 之前我们提到过test方法,该方法确实行之有效,但是使用起来还是需要注意一些地方。
比如我要验证一个手机号,那我可以使用 /1[3-8]\d{9}/.test(18212345678)这个一定是返回true的,但是如果我在电话后面不小心多写了一个0,即/1[3-8]\d{9}/.test(18212345678) 这个同样也会返回true,因为test如果只是检测到存在,就说明true,所以这时比较好的解决办法就是加$,如 /^1[3-8]\d{9}$/.test(18212345678) 就非常奏效了。
2. 正则表达式中匹配的都是字符串,并且我们知道表单中的value也都是字符串。
注:原创文章,如需转载,请注明出处。博客地址:http://www.cnblogs.com/zhuzhenwei918/p/6204445.html
千淘万漉虽辛苦,吹尽狂沙始到金。