今天突然在数据库中发现这样一个手机号1787878787878
,
可以发现,比正常的手机号多了两位,但是这些都是在前端通过正则校验的,
下面是前端用的正则,看起来似乎没有问题(早期版本,忽略它繁琐的写法,此处只讨论问题)
/^(13[0-9]{9})|(15[0-9]{9})|(17[0-9]{9})|(18[0-9]{9})|(19[0-9]{9})$/;
co 出来一段测试一番,问题很奇怪
regex1 = /^(17[0-9]{9})$/;
regex2 = /^(19[0-9]{9})$/;
regex3 = /^(17[0-9]{9})|(19[0-9]{9})$/;
console.log(regex1.test('1787878787878')); // false
console.log(regex2.test('1787878787878')); // false
console.log(regex3.test('1787878787878')); // true
console.log(regex3.test('1987878787878')); // false
^
表示开头,即被匹配的字符串只能以^
后的字符开头
$
表示结尾,即被匹配的字符串只能以$
前的字符结尾
如果同时使用^
和$
, 则要求字符串必须完全符合正则表达式
所以上面的regex3
中的^
和$
分别与左侧和右侧的分式结合了,只是代表着 17 开头或者以 9 个数字结尾的字符串,并不是完全匹配 11 个字符的长度。下面还有一个例子用来证明:
regex4 = /^(17[0-9]{9})|(18[0-9]{9})|(19[0-9]{9})$/;
console.log(regex4.test('a18888888888b')); // true
该表达式表明:第二个式子完全没有匹配字符串的开头和结尾。
不出所料,这样写就对了
regex5 = /(^17[0-9]{9}$)|(^19[0-9]{9}$)/;
console.log(regex5.test('1787878787878')); // false
所以若是采用这种写法,应当在每个小括号内都加上^
和$
。
或者采用这种更完善的写法 /^1[3-9][0-9]{9}$/