正则表达式常见坑与分析法
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
这个开发者文档就是好,讲得比w3school还清楚
稍稍看看文档,对照着就开始用吧。
为啥要用正则呢?不用多说了吧,一行正则匹配,顶上十来行字符串[拼接、分割、截取]的操作
字符串中的斜杆
\
有
转义
的特殊意义,在写正则规则的时候请注意
\
代表的意思
字符串中两个
\
代表一个
/^ $/
中间的内容是只能包含的意思,而不是很多教程中提到的 以xxx开头 ,以xxx结尾,多了一层
并且
的意思,所以规则是
只能
/^a$/
匹配以a开头,以a结尾的字符 所以 只能是a
/^ab$/
匹配以a开头,以b结尾的字符 所以只能是 ab
x|y
迷惑的
|
匹配运算,优先级很混乱记得搭配上
()
来使用,
()
在正则中表示一个分组匹配意为先
结合
解决优先级问题
let reg = /^18|29$/;
console.log(reg.test("1829")) //=> true
console.log(reg.test("189")) //=>true
console.log(reg.test("129")) //=>true
console.log(reg.test("89")) //=>false
let reg = /^(18|29)$/; 这样才符合我们想要的情况
let reg = /^[@+]+$/; // 只能是以@+中的任何一个开头,且它出现一次或者多次的匹配,[]里面的`+`就是本身意义
console.log(reg.test("@@")) // => true
console.log(reg.test("@@"))
:\d
组合词的本身含义就是 0 ~ 9
let reg = /^[\d]$/ // => 这个 `\d` 还是原始的 `\d`的意思 0 ~ 9 之间的数字
console.log(reg.test("d")) //false
console.log(reg.test("\\")) //false
console.log(reg.test("9")) //true
console.log(reg.test("8")) //true
console.log(reg.test("9")) //true
console.log(reg.test("18")) //false
此处翻译为: 只能是 1 或者 8
let reg = /^[10-29]$/
此处翻译为:只能是 1 或者 0到2 或者9
let reg = /^[18-29]$/
而这里会提示 是错误的正则式,Range out of order in character class 字符内的范围无序
: 就算在 /^[10-29]$/
中加入()
,\
也不行
遇到|
使用()
确定好正则的优先级(()
的作用一:细节用法看分析法第一条)
把大正则中的每个小正则 配合 exec
方法提取出来(()
的作用二:细节用法看分析法第五条)
1、是否为有效数
有如下数字需要正则匹配():验证是否属于一个合法数字
提取条件出来:
1. 可能出现 + - 号,也可能没有,且有且只有一个
2. 0 - 9 都可以,但是多位数首位不能是 0
3. 小数部分可能有,可能没有,有的话有且只有一个点,且点后必须有数字
转化为正则表达式
let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
[+-]? +或者-出现 0 或者 1 次
(+|-)? 与上面相等
(\d|([1-9]\d+))
\d为出现一位,
或者多位时,首位不能为零,则再用一个 () 表示一个小分组,且每次遇到 | 的时候使用 ()包起来
([1-9]\d+) 这里表示小分组是 或的另外一边的一个整体, 1 - 9 出现一次 或者多次
+ 为匹配前面的表达式出现一次或者多次
2、密码的有效性
需求:密码是 6 - 16位,可以是数字、字母、下划线
let reg = /^(\w){6,16}$/
3、真实姓名验证
验证汉字:/^[\u4E00-\u9FA5]$/
有可能是翻译过来的汉字名:肯多·洛夫斯基,也可能是新疆人名字尼格买提·阿布都(·汉字)
名字长度2 ~ 10位
测试用例可以使用:
肯多·洛夫斯基
尼格买提·阿布都
弗拉基米尔·弗拉基米罗维奇·普京
莱昂纳多·迪·皮耶罗·达·芬奇
let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
5、身份证号码验证
中国第二代居民身份证规则为:
目前为止只有18位
最后一位可能是大写的X (代表是10)
身份证前6位代表居民所在省、市、县
中间八位是出生年月日
最后四位:
最后一位 X 或者 数字
倒数第二位 偶数为女 ,奇数为男
其余两位是经过算法 结合前6、中8,后2位算出来的(非随机)
/*如果只考虑位数与字符,不考虑字符意义*/
let reg = /^(\d+){17}(\d|X)$/
let reg = /^(\d+X{0,1}){18}$/ /*这样写不行,必须拆开前17位 + 后一位才行*/
/*附带意义的匹配*/
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|X)$/
reg.exec("430181199003073470")
使用exec
来捕获()
匹配出来的每一个小分组,结果为:
["430181199003073470", "430181", "1990", "03", "07", "34", "7", "0", index: 0, input: "430181199003073470", groups: undefined]
6、获取cookie值
cookie 的规则:
字符串开头有可能有空格,可能没有(第一条就没有)
接着后面是 key= 的固定样式
字符串结束有可能有分号,可能没有(最后一条没有分号)
利用构造函数方式来获取指定的 cookie key 名的值
function (key) {
let reg = RegExp("(^| )"+key+"=([^;]*)(;|$)");
* exec 有几个括号就至少有几个分组
* 匹配一个开头,空格可有可无 (可能匹配的是第一条,所以空格可有可无)
* 接着后面的 字符是 key=
* 匹配任何没有包含在方括号中的字符 (只要不是分号就可以)
* 星号 = {0,} 出现零次或者多次,意味着 cookie有时候会是 null值
* 匹配结束 分号可有可无(可能匹配的是最后一条,所以分号可有可无)(只能包含 ^ $ 中间的东西)
[" name=zhangsan", " ", "zhangsan", "", index: 22, input: "age=21; handsome=true; name=zhangsan", groups: undefined]
如果 传入参数 name,匹配之后:
* 可以看到 name 前面有空格,
* 第一项为 匹配出来的总结果
* 第二项的 " " 为 小分组 (^| ) 所捕获
* 第三项的 "zhangsan" 为 小分组([^;]*)所捕获 这正是我们想要的
* 第四项的 "" 为 小分组(;|$) 所捕获
// 返回的数组中 input 是原生字符串 是 document.cookie
正则表达式的两种创建方式
1、字面量方式
let reg = /@+name+/
/ /
中间包含的任意字符都会被识别成为 正则表达式的元字符
如果这个时候要将 传过来的变量 name
来进行独立的个体匹配,那是不行的,这个时候就应该用 构造函数方式
来创建 字符串拼接
的表达式
注意:使用正则表达式字面量为正则表达式提供了脚本加载后的编译。当正则表达式保持不变时,使用此方法可获得更好的性能。
2、构造函数方式
new RegExp(pattern,flags)
pattern
:正则表达式
flags
:匹配模式
let reg = new RegExp("@"+name+"+")
且在使用模式的时候需要传入第二个参数flags
字面量的方式可以紧随最后一个/
其后
注意:使用构造函数为正则表达式提供了运行时的编译。使用构造函数的方式,当你知道正则表达式的模式将会改变,或者你不知道模式,并且从其他来源获取它,如用户输入。
var regex1 = /\w+/;
var regex2 = new RegExp('\\w+'); //在字符串中 单条斜杆加上斜杆后字符代表转义字符
console.log(regex1);
// expected output: /\w+/
console.log(regex2);
// expected output: /\w+/