前言
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)$/; 这样才符合我们想要的情况 */
-
reg.test(str)
-
str.match(reg)
-
reg.exec(str)
-
[]
中出现的规则一般都是本身的含义let reg = /^[@+]+$/; // 只能是以@+中的任何一个开头,且它出现一次或者多次的匹配,[]里面的`+`就是本身意义 console.log(reg.test("@@")) // => true console.log(reg.test("@@"))
注 意 例 外 \color{#e15c5f}{注意例外} 注意例外:
\d
组合词的本身含义就是 0 ~ 9let reg = /^[\d]$/ // => 这个 `\d` 还是原始的 `\d`的意思 0 ~ 9 之间的数字 console.log(reg.test("d")) //false console.log(reg.test("\\")) //false console.log(reg.test("9")) //true
-
[]
中不存在多位数let reg = /^[18]$/ 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 字符内的范围无序
注 意 \color{#ff0000}{注意} 注意: 就算在
/^[10-29]$/
中加入()
,\
也不行 -
在写正则表达式的时候一定要注意 顺序是
从左往右就近匹配
的,善用小整体()
-
遇到
|
使用()
确定好正则的优先级(()
的作用一:细节用法看分析法第一条) -
把大正则中的每个小正则 配合
exec
方法提取出来(()
的作用二:细节用法看分析法第五条)
常用正则表达式分析
1、是否为有效数
- 有如下数字需要正则匹配():验证是否属于一个合法数字
0
1
12
12.5
12.0
-12
+12
09
提取条件出来:
/*
1. 可能出现 + - 号,也可能没有,且有且只有一个
2. 0 - 9 都可以,但是多位数首位不能是 0
3. 小数部分可能有,可能没有,有的话有且只有一个点,且点后必须有数字
*/
转化为正则表达式
let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
/*
条件1:
[+-]? +或者-出现 0 或者 1 次
(+|-)? 与上面相等
条件2:
(\d|([1-9]\d+))
\d为出现一位,
或者多位时,首位不能为零,则再用一个 () 表示一个小分组,且每次遇到 | 的时候使用 ()包起来
([1-9]\d+) 这里表示小分组是 或的另外一边的一个整体, 1 - 9 出现一次 或者多次
+ 为匹配前面的表达式出现一次或者多次
*/
2、密码的有效性
需求:密码是 6 - 16位,可以是数字、字母、下划线
/**/
let reg = /^(\w){6,16}$/
3、真实姓名验证
需求:
验证汉字:/1$/
有可能是翻译过来的汉字名:肯多·洛夫斯基,也可能是新疆人名字尼格买提·阿布都(·汉字)
名字长度2 ~ 10位
测试用例可以使用:
- 肯多·洛夫斯基
- 尼格买提·阿布都
- 弗拉基米尔·弗拉基米罗维奇·普京
- 莱昂纳多·迪·皮耶罗·达·芬奇
let reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10})*$/
4、邮箱格式验证
xxxxx@xxxx.com
- 以数字字母下划线开头(下划线有些邮箱也可以出现多次)
- @前面可以是数字、字母、下划线、一、.这些符号
- 不能把-和.连续出现,出现一次后面必须跟数字字母下划线
- @后面的紧跟数字、字母 ,一到多位
- 企业邮箱.com.cn多域名情况
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
7、获取url路径中的参数
let reg = /(&|\?)([^=]*)=([^&]*)(&|$)/g
temp = ""
let obj = {
}
while(temp !== null){
temp = reg.exec(s)
if (temp === null)
break
else{
//console.log(`${temp[2]}=${temp[3]}`)
obj[temp[2]] = temp[3]
reg.lastIndex--
}
}
console.log(obj)
用到的是
exec()
这个函数,且加了g
全局(贪婪)匹配修饰符,这个函数每一次单独运行都会匹配出一组结果,如果想要获取全部的匹配结果,唯一的方式就是通过把exec()
放循环里面,我被这个坑点坑过不少回,长记性了。
w3School原话:
正则表达式的两种创建方式
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+/
console.log(regex1 === regex2); //两个虽然输出一样,但是不相等
// expected output: false
\u4E00-\u9FA5 ↩︎