今天一大早遇就遇到一件诡异的事儿,多是思绪尚未澄静下来,一会儿没反应过来。事情是这样的:正则表达式
模板:spa
<input class="name" type="text" placeholder="username"> <button type="submit">submit</button>
脚本:code
$("button").click(function(event) { event.preventDefault(); var $name = $(".name").val(); // 用户名:以数字、字母或下划线开头,有6-20位 var reg_name = /^[a-zA-Z0-9_]{1}[a-zA-Z0-9\*\._]{5,19}$/g; console.log(reg_name.test($name)); if (reg_name.test($name)) { console.log("correct!"); } else { console.log("error!"); } });
输出:对象
true error!
我在输入框内填入“qqqqqq”,提交,我瞬间懵了,这这这,返回true了,你还给我走false分支?!此事必有蹊跷。。。待我inner peace了一下以后,稍做调整,代码正常了:blog
脚本:字符串
$("button").click(function(event) { event.preventDefault(); var $name = $(".name").val(); // 用户名:以数字、字母或下划线开头,有6-20位 var reg_name = /^[a-zA-Z0-9_]{1}[a-zA-Z0-9\*\._]{5,19}$/; console.log(reg_name.test($name)); if (reg_name.test($name)) { console.log("correct!"); } else { console.log("error!"); } });
输出:get
true correct!
我把正则表达式对象后边的“g”修饰符给去掉以后,代码可正常运转。话说这个“g”的意思是:执行一个全局匹配,也即找到目标字符串中全部与表达式匹配的字符。而每一次执行exec(),只要一匹配到符合条件的字符,这个方法就立马返回匹配的对象,它又是如何找到全部匹配的字符呢?这又牵扯到RegExp对象的lastIndex属性,这个属性返回的是与匹配的字符紧邻的位置,也即第一个不与表达式匹配的字符的位置。这样,咱们来个栗子:input
脚本:string
var str = "cat, fat, bat, pat"; var reg = /.al/g; var match = reg.exec(str); console.log(match + ": " + match.index + "," + match[0] + "," + reg.lastIndex); match = reg.exec(str); console.log(match + ": " + match.index + "," + match[0] + "," + reg.lastIndex);
输出:it
cat: 0,cat,3
fat: 5,fat,8
上述代码,咱们能够看到,我对该字符串执行了两次exec()方法,第一次,它匹配到了“cat”字符,lastIndex指的就是第一个“,”所在的位置,也即3,第二次,匹配到了“fat”字符,此时lastIndex指的就是第二个“,”所在的位置,也即8,lastIndex就像一个书签,它记录着每一次匹配进行的位置。咱们来换一个方式,看“g”修饰符如何尽情施展拳脚:
脚本:
var str = "cat, fat, bat, pat"; var reg = /.at/g; while((matche = reg.exec(str)) != null) { console.log(matche + "," + matche.index + "," + matche[0] + "," + reg.lastIndex); }
输出:
cat,0,cat,3 fat,5,fat,8 bat,10,bat,13 pat,15,pat,18
喏,全部字符都如愿以偿的被匹配了,这就是“g”和“lastIndex”的强大之处。固然,我也知道了上述的诡异问题还有一个问题就是我对该字符串进行了两次匹配,以前只知道test()方法返回布尔值,exec()方法返回匹配的结果,感受test()只是一把小刀,功能并无exec()强大,查了一下资料才发现并否则。
原话是这么说的:“其实,调用test()和调用exec()是等价的,当exec()返回的结果不是null时,test()返回true,因为这种等价性,当一个全局正则表达式调用test()方法时,它的行为和exec()相同,由于它从lastIndex指定的位置开始检索某个字符,若是找到了一个匹配结果,就马上设置lastIndex的值为当前匹配子串的结束位置,这样一来,就可使用test()方法来遍历字符串,就像使用exec()同样。”(《权威指南》)
所以,咱们在写正则的时候,必定要注意修饰符及方法的使用,若使用不当,势必会对下次匹配形成不肯定的影响,同时也要记得,不要在正则表达式里加入空格,这一样会对结果有影响。
最后再附几个经常使用的正则:
// 用户名:以数字、字母或下划线开头,有6-20位
var reg_name = /^[a-zA-Z0-9_]{1}[a-zA-Z0-9\*\._]{5 , 19}$/;
// 密码:只能输入6~20位的数字、字母、下划线、*
var reg_pwd = /^[\w\*]{6,20}$/;
// 手机号:能够以+或数字开头,也能够含有“—”和“ ”
var reg_phone = /^[+]?(\d){3}[\s|-]?(\d){4}[\s|-]?(\d){4}$/;
//时间:年月日--- 2016-01-20 16-02-02 20160202
var reg_time = /^\d{2}|\d{4}[-]?((0([1-9]{1}))|1[1|2])[-]?((0[1-9])|[1|2]\d)|(3|[0|1])$/;
// 邮箱:***@**.***
function isEmail (theStr) {
var atIndex = theStr.indexOf('@');
var dotIndex = theStr.indexOf('.', atIndex);
var flag = true;
theSub = theStr.substring(0, dotIndex+1)
if ((atIndex < 1)||(atIndex != theStr.lastIndexOf('@'))||(dotIndex < atIndex + 2)||(theStr.length <= theSub.length)) {
return(false);
}else {
return(true);
}}