# 正则表达式
正则表达式是用于匹配字符串中字符组合的模式,在 JavaScript中,正则表达式也是对象。
与普通函数操作字符串来比较,正则表达式可以写出更简洁、功能强大的代码。
# 创建正则
JS提供字面量与对象两种方式创建正则表达式
# 字面量创建
使用 //
包裹的字面量创建方式是推荐的作法,但它不能在其中使用变量
let web = "jc-sir.github.io";
console.log(/u/.test(web));//true
下面尝试使用 a 变量时将不可以查询
let web = "jc-sir.github.io";
let a = 'u';
console.log(/a/.test(web));//true
虽然可以使用 eval
转换为js语法来实现将变量解析到正则中,但是比较麻烦,所以有变量时建议使用下面的对象创建方式
let web = "jc-sir.github.io";
let a = 'u';
console.log(eval(`/${a}/`).test(web));//true
# 对象创建
当正则需要动态创建时使用对象方式
let web = "jc-sir.github.io";
let subStr = "sir";
let reg = new RegExp(subStr);
console.log(reg.test(web)); //true
# 选择符
|
这个符号带表选择修释符,也就是 |
左右两侧有一个匹配到就可以。
判断字符串中是否含有test或者jcsir
var str = "test the regExp!";
console.log(/test|jcsir/.test(str)) // true
# 字符转义
转义用于改变字符的含义,用来对某个字符有多种语义时的处理。
如果我们想通过正则查找/
符号,但是/
在正则中有特殊的意义。如果写成///
这会造成解析错误,所以要使用转义语法 /\//
来匹配。
const url = "http://jc-sir.githuo.io";
// 是否有'http://'
console.log(/http:\/\//.test(url)); //true
使用 RegExp 构建正则时在转义上会有些区别,下面是对象与字面量定义正则时区别
let price = 12.23;
//含义1: . 除换行外任何字符 含义2: .普通点
//含义1: d 字母d 含义2: \d 数字 0~9
console.log(/\d+\.\d+/.test(price));
//字符串中 \d 与 d 是一样的,所以在 new RegExp 时\d 即为 d
console.log("\d" == "d");
//使用对象定义正则时,可以先把字符串打印一样,结果是字面量一样的定义就对了
console.log("\\d+\\.\\d+");
let reg = new RegExp("\\d+\\.\\d+");
console.log(reg.test(price));
# 字符边界
使用字符边界符用于控制匹配内容的开始与结束约定。
边界符号 | 说明 |
---|---|
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束,忽略换行符 |
示例
匹配内容必须以www开始
var url = "www.jc-sir.github.io"
console.log(/^www/.test(url)) //true
匹配内容必须以 .io 结束
console.log(/.io$/.test(url)) //true
检测用户名长度为3~6位,且只能为字母。如果不使用 ^与$ 限制将得不到正确结果
let reg = /^[a-z]{3,6}$/i
console.log(reg.test("sjkfds")); // true
console.log(reg.test("sjkfd1ds")); // false
# 元子字符
元字符是正则表达式中的最小元素,只代表单一(1个)字符
元字符 | 说明 | 示例 |
---|---|---|
\d | 匹配任意一个数字 | [0-9] |
\D | 与除了数字以外的任何一个字符匹配 | [^0-9] |
\w | 与任意一个英文字母,数字或下划线匹配 | [a-zA-Z_] |
\W | 除了字母,数字或下划线外与任何字符匹配 | [^a-zA-Z_] |
\s | 任意一个空白字符匹配,如空格,制表符\t,换行符\n | [\n\f\r\t\v] |
\S | 除了空白符外任意一个字符匹配 | [^\n\f\r\t\v] |
. | 匹配除换行符外的任意字符 |
# 使用示例
匹配任意数字
let test = "This is 2020";
console.log(test.match(/\d/g)); //["2", "0", "2", "0"]
// + 代表匹配一个或者多个
console.log(test.match(/\d+/g)); //["2020"]
let test = "This is 20 20";
console.log(test.match(/\d{1,2}/g)); //["20", "20"]
匹配任意非数字
console.log(/\D/.test(2029)); //false
console.log('this is 2020'.match(/\D+/g)); // ["this is "]
匹配所有电话号码
let tel = `张三:010-99999999,李四:020-88888888`;
let res = tel.match(/\d{3}-\d{7,8}/g);
console.log(res); //["010-99999999", "020-88888888"]
匹配字母数字下划线
let regstr = "this is jc-sir.github.io_";
console.log(regstr.match(/\w+/g));
// ["this", "is", "jc", "sir", "github", "io_"]
匹配除了字母,数字或下划线外与任何字符匹配
let regstr = "this is jc-sir.github.io_";
console.log(regstr.match(/\W+/g));
// [" ", " ", "-", ".", "."]
匹配与任意一个空白字符匹配
console.log(/\s/.test(" ")); //true
console.log(/\s/.test("\n")); //true
console.log(/\s/.test("\f")); //true
console.log(/\s/.test("\r")); //true
console.log(/\s/.test("\t")); //true
console.log(/\s/.test("\v")); //true
匹配除了空白符外任意一个字符匹配
let web = "this js-sir.github.io ";
console.log(web.match(/\S+/g));
// ["this", "js-sir.github.io"]
如果要匹配点则需要转义
因为.
匹配除换行符外
的任意字符
let baidu = "www.baidu@com"
console.log(/baidu.com/i.test(baidu)); //true
console.log(/baidu\.com/i.test(baidu)); //false
// 因为换行符 后面的将被忽略
let url = `
https://www.baidu.com
jc-sir.githu.io
`;
console.log(url.match(/.+/)[0]); //https://www.baidu.com
使用 /s
视为单行模式(忽略换行)时,.
可以匹配所有
正则中空格会按普通字符对待
let url = `
https://www.baidu.com
jc-sir.githu.io
`;
let reg = url.match(/./s);
console.log(reg[0])
// https://www.baidu.com
// jc-sir.githu.io
# 所有字符
可以使用 [\s\S] 或 [\d\D] 来匹配所有字符
# 模式修饰
正则表达式在执行时会按他们的默认执行方式进行,但有时候默认的处理方式总不能满足我们的需求,所以可以使用模式修正符更改默认方式。
修饰符 | 说明 |
---|---|
i | 不区分大小写字母的匹配 |
g | 全局搜索所有匹配内容 |
m | 视为多行 |
s | 视为单行忽略换行符,使用. 可以匹配所有字符 |
y | 从 regexp.lastIndex 开始匹配 |
u | 正确处理四个字符的 UTF-16 编码 |
# i
不区分大小写
let Str = "This Is My blog";
let reg = /i/gi;
console.log(Str.match(reg)); // [i,I]
let reg = /i/g;
console.log(Str.match(reg)); // [i]
// 替换成小写
console.log(Str.replace(reg,"i"));
// This is my blog
# g
使用 g
修饰符可以全局操作内容
不使用则匹配到第一个将停止继续匹配
# m
用于将内容视为多行匹配,主要是对 ^和 $ 的修饰
示例
将下面是将以 #数字开始的编程语言解析为对象结构
let proStr = `
#1 js,前端 #
#2 php,后端 #
#9 java,后端 # 最牛逼的编程语言
#3 css, 前端#
`;
let regExp = /^\s+#\d\s+.+\s+#$/gm;
let language = proStr.match(regExp).map(v=>{
v = v.replace(/\s*#\d+\s*/,"").replace(/\s+#/,"");
[name,type] = v.split(",");
return {name,type};
})
console.log(JSON.stringify(language,null,2));
// 执行结果
[
{
"name": "js",
"type": "前端"
},
{
"name": "php",
"type": "后端"
}
]
# u
每个字符都有属性,如 L
属性表示是字母,P
表示标点符号,需要结合 u
模式才有效
//使用\p{L}属性匹配字母
let blog = "Jc-sir.github.io.个人博客!";
console.log(blog.match(/\p{L}+/gu));
// ["Jc", "sir", "github", "io", "个人博客"]
//使用\p{P}属性匹配标点
console.log(blog.match(/\p{P}+/gu));
// ["-", ".", ".", ".", "!"]
字符也有unicode文字系统属性 Script=文字系统
,下面是使用 \p{sc=Han}
获取中文字符 han为中文系统.
let blog = "博客,Jc-sir.github.io.个人博客!";
let res = blog.match(/\p{sc=Han}+/gu);
console.log(res)
// ["博客","个人博客"]
使用 u
模式可以正确处理四个字符的 UTF-16
字节编码
let str = "𝒳𝒴";
console.table(str.match(/[𝒳𝒴]/)); //结果为乱字符"�"
console.table(str.match(/[𝒳𝒴]/u)); //结果正确 "𝒳"
# lastIndex
RegExp对象lastIndex
属性可以返回
或者设置正则表达式开始匹配的位置
- 必须结合 g 修饰符使用
- 对 exec 方法有效
- 匹配完成时,lastIndex 会被重置为0
let blog = "我的博客地址:jc-sir.github.io";
let reg = /\p{sc=Han}/gu;
while ((res = reg.exec(blog))) {
console.log(res[0]);
}
// 控制台看结果
# y
使用y
模式后如果从 lastIndex
开始匹配不成功就不继续匹配了
let blog = "jc-sir.github.io sir";
let reg = /sir/y;
reg.lastIndex = 3;
console.log(reg.exec(blog));
console.log(reg.lastIndex); // 6
console.log(reg.exec(blog)); // null
console.log(reg.lastIndex); // 0
# 原子表
在一组字符中匹配某个元字符,在正则表达式中通过元字符表来完成,就是放到[]
(方括号)中
# 使用语法
原子表 | 说明 |
---|---|
[] | 只匹配其中的一个原子 |
[^] | 只匹配"除了"其中字符的任意一个原子 |
[0-9] | 匹配0-9任何一个数字 |
[a-z] | 匹配小写a-z任何一个字母 |
[A-Z] | 匹配大写A-Z任何一个字母 |
# 使用示例
使用 []
匹配其中任意字符即成功
let blog = "this is my blog!";
console.log(/mg/.test(blog)); // false
console.log(/[mg]/.test(blog)) // true
匹配日期格式 -
或者/
let date = "2022-02-23";
console.log(date.match(/\d{4}([-\/])\d{2}\1\d{2}/));
区间内数字匹配
const num = "2";
console.log(/[0-3]/.test(num)); //true
匹配a~f间的任意字符
const char = "e";
console.log(/[a-f]/.test(char)); //true
顺序为升序否则将报错
const num = "2";
console.log(/[3-0]/.test(num)); //SyntaxError
字母也要升序否则也报错
const blog = "jc-sir.github.io";
console.log(/[f-a]/.test(blog)); //SyntaxError
获取所有用户名
let str = `
张三:010-99999999,李四:020-88888888`;
let reg = /[^:\d-,\n]+/g;
console.log(str.match(reg)); // ["张三", "李四"]
原子表中有些正则字符不需要转义,如果转义也是没问题的,可以理解为在原子表中. 就是小数点
let str = "(jc-sir.github.io)+";
console.table(str.match(/[().+]/g));
//使用转义也没有问题
console.table(str.match(/[\(\)\.\+]/g));
# 原子组
- 原子组与原子表的差别在于原子组一次匹配多个元子,而原子表则是匹配任意一个字符。
- 元字符组用 () 包裹
← 深入理解原型与原型链 js 事件循环机制 →