先贴一份正则常用的规则。
元字符 说明 示例
\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]
. 匹配除换行符外的任意字符 含义1. 除换行外任何字符 含义2: \. 普通点
修饰符 说明
i 不区分大小写字母的匹配
g 全局搜索所有匹配内容
m 视为多行
s 视为单行忽略换行符,使用. 可以匹配所有字符
y 从 regexp.lastIndex 开始匹配
u 正确处理四个字符的 UTF-16 编码
原子表 说明
[] 只匹配其中的一个原子
[^] 只匹配"除了"其中字符的任意一个原子
[0-9] 匹配 0-9 任何一个数字
[a-z] 匹配小写 a-z 任何一个字母
[A-Z] 匹配大写 A-Z 任何一个字母
原子组
变量 说明
0 匹配到的完整内容
1,2.... 匹配到的原子组
index 原字符串中的位置
input 原字符串
groups 命名分组
实战练习
- 查出所有的数字
let hd = "houdunren2200hdcms9988";
console.log(hd.match(/\d/g));//['2', '2', '0', '0', '9', '9', '8', '8']
- 创建正则 & 变量使用
创建正则 & 变量使用
let hd = "houdunren.com";
console.log(/u/.test(hd));//true
const key = 'u'
console.log(/key/.test(hd));//false
console.log(eval(`/${key}/`).test(hd));
对象创建
let hd = "houdunren.com";
let web = "houdunren";
let reg = new RegExp(web);
console.log(reg.test(hd));
- 高亮字符
<div id="content">houdunren.com</div>
3. 高亮字符
const content = prompt("请输入要搜索的内容,支持正则表达式");
const reg = new RegExp(content,'g')
const dom = document.getElementById('content')
dom.innerHTML = dom.innerHTML.replace(reg,str=>{
return `<span style="color:red">${str}</span>`
})
- 选择符, | 这个符号带表选择修释符,也就是 | 左右两侧有一个匹配到就可以。 检测电话是否是上海或北京的坐机
let tel = "010-12345678"; // let tel = "010-1";
//错误结果:只匹配 | 左右两边任一结果 "010"
console.log(tel.match(/010|020\-\d{7,8}/));// 010-12345678 | 010
//正确结果:所以需要放在原子组中使用
console.log(tel.match(/(010|020)\-\d{7,8}/));// 010-12345678
- 字符转义
假如有这样的场景,如果我们想通过正则查找/符号,但是 /在正则中有特殊的意义。
如果写成///这会造成解析错误,所以要使用转义语法 / \/ /来匹配。
const url = "https://www.houdunren.com";
console.log(/https:\/\//.test(url))//true
console.log(/^https?:\/\/\w+\.\w+\.\w+$/.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");// true
//使用对象定义正则时,可以先把字符串打印一样,结果是字面量一样的定义就对了
console.log("\\d+\\.\\d+");
let reg = new RegExp("\\d+\\.\\d+");
console.log(reg.test(price));
- 字符边界
使用字符边界符用于控制匹配内容的开始与结束约定。
边界符 说明
^ 匹配字符串的开始
$ 匹配字符串的结束,忽略换行符
const hd = "www.houdunren.com";
console.log(/^www\.\w+\.com$/.test(hd)); //true
检测用户名长度为 3~6 位,且只能为字母。如果不使用 ^与$ 限制将得不到正确结果
document
.querySelector(`[name="username"]`)
.addEventListener("keyup", function() {
let res = this.value.match(/^[a-z]{3,6}$/i);
console.log(res);
console.log(res ? "正确" : "失败");
});
- 元子字符
元字符 说明 示例
\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]
. 匹配除换行符外的任意字符 含义1. 除换行外任何字符 含义2: \. 普通点
匹配任意数字
let hd = "houdunren 2010";
console.log(hd.match(/\d/g)); //["2", "0", "1", "0"]
匹配所有电话号码
let hd = `张三:010-99999999,李四:020-88888888`;
let res = hd.match(/\d{3}-\d{7,8}/g);
console.log(res);
获取所有用户名
let hd = `张三:010-99999999,李四:020-88888888`;
let res = hd.match(/[^:\d-,]+/g);
console.log(res);
匹配任意非数字
console.log(/\D/.test(2029)); //false
匹配字母数字下划线
let hd = "hdcms@";
console.log(hd.match(/\w/g)); //["h", "d", "c", "m", "s"]
匹配除了字母,数字或下划线外与任何字符匹配
console.log(/\W/.test("@")); //true
匹配与任意一个空白字符匹配
console.log(/\s/.test(" ")); //true
console.log(/\s/.test("\n")); //true
匹配除了空白符外任意一个字符匹配
let hd = "hdcms@";
console.log(hd.match(/\S/g)); // ['h', 'd', 'c', 'm', 's', '@']
如果要匹配点,则需要转义
let hd = `houdunren@com`;
console.log(/houdunren.com/i.test(hd)); //true 含义1. 除换行外任何字符 含义2: \. 普通点
console.log(/houdunren\.com/i.test(hd)); //false
使用.匹配除换行符外任意字符,下面匹配不到hdcms.com 因为有换行符
const url = `
https://www.houdunren.com
hdcms.com
`;
console.log(url.match(/.+/)[0]);// https://www.houdunren.com
使用/s视为单行模式(忽略换行)时,. 可以匹配所有
let hd = `
<span>
houdunren
hdcms
</span>
`;
console.log(hd.match(/<span>.*<\/span>/s)[0]);
正则中空格会按普通字符对待
let tel = `010 - 999999`;
console.log(/\d+-\d+/.test(tel));
console.log(/\d+ - \d+/.test(tel));
console.log(/^\d{3} - \d{6}$/.test(tel));
所有字符 可以使用 [\s\S] 或 [\d\D] 来匹配所有字符
let hd = `
<span>
houdunren
hdcms
</span>
`;
console.log(hd.match(/[\s\S]+/)[0]);
- 模式修饰
修饰符 说明
i 不区分大小写字母的匹配
g 全局搜索所有匹配内容
m 视为多行
s 视为单行忽略换行符,使用. 可以匹配所有字符
y 从 regexp.lastIndex 开始匹配
u 正确处理四个字符的 UTF-16 编码
i 将所有houdunren.com 统一为小写
let hd = "houdunren.com HOUDUNREN.COM";
hd = hd.replace(/houdunren\.com/gi,'houdunren.com')
console.log(hd);
g 使用 g 修饰符可以全局操作内容
let hd = "houdunrenuuu";
hd = hd.replace(/u/,'@')
console.log(hd);//ho@dunrenuuu
hd = hd.replace(/u/g,'@')
console.log(hd);//ho@d@nren@@@
m 用于将内容视为多行匹配,主要是对 ^和 $ 的修饰
let hd = `
#1 js,200元 #
#2 php,300元 #
#9 houdunren.com # 你爷爷
#3 node.js,180元 #
`;
const res = hd.match(/^\s*#\d+\s+.+\s+#$/gm).map(v =>{
v = v.replace(/^\s*#\d+\s+/,'').replace(/^\s+#\s*/,'')
const [name,price] = v.split(',')
return {name,price}
})
console.log(res);
u 每个字符都有属性,如L属性表示是字母,P 表示标点符号,需要结合 u 模式才有效。其他属性简写可以访问 属性的别名
使用\p{L}属性匹配字母
let hd = "houdunren2010.不断发布教程,加油!";
console.log(hd.match(/\p{L}+/gu)[0]);//"houdunren"
使用\p{P}属性匹配标点
console.log(hd.match(/\p{P}+/gu));
lastIndex
RegExp 对象lastIndex 属性可以返回或者设置正则表达式开始匹配的位置
必须结合 g 修饰符使用
对 exec 方法有效
匹配完成时,lastIndex 会被重置为 0
let hd = `后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
let reg = /后盾人(.{2})/g;
reg.lastIndex = 10; //从索引10开始搜索
console.log(reg.exec(hd));
console.log(reg.lastIndex);
let hd = `后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
reg = /\p{sc=Han}/gu;
while(res = reg.exec(hd)){
console.log(res);
}
y 我们来对比使用 y 与g 模式,使用 g 模式会一直匹配字符串
但使用y 模式后如果从 lastIndex 开始匹配不成功就不继续匹配了
let hd = "udunren";
let reg = /u/y;
console.log(reg.exec(hd));
console.log(reg.lastIndex); //1
console.log(reg.exec(hd)); //null
console.log(reg.lastIndex); //0
因为使用 y 模式可以在匹配不到时停止匹配,在匹配下面字符中的 qq 时可以提高匹配效率
let hd = `后盾人QQ群:11111111,999999999,88888888后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
let reg = /(\d+),?/y;
reg.lastIndex = 7;
while ((res
- 原子表
原子表 说明
[] 只匹配其中的一个原子
[^] 只匹配"除了"其中字符的任意一个原子
[0-9] 匹配 0-9 任何一个数字
[a-z] 匹配小写 a-z 任何一个字母
[A-Z] 匹配大写 A-Z 任何一个字母
使用[]匹配其中任意字符即成功,下例中匹配ue任何一个字符,而不会当成一个整体来对待
const url = "houdunren.com";
console.log(/ue/.test(url)); //false
console.log(/[ue]/.test(url)); //true
日期的匹配 *** ([-\/]) \1 原子组
let tel = "2022-02-23"; //"2022-02/23";
let reg = /^\d{4}([-\/])\d{2}\1\d{2}$/
console.log(tel.match(reg),reg.test(tel));
const num = "2";
console.log(/[0-3]/.test(num)); //true
const hd = "e";
console.log(/[a-f]/.test(hd)); //true
^的使用 -- 排除匹配
let hd = `
张三:010-99999999,李四:020-88888888`;
let res = hd.match(/[^:\d-,\s]+/g);
console.log(res);
原子表中有些正则字符不需要转义,如果转义也是没问题的,可以理解为在原子表中. 就是小数点
let str = "(houdunren.com)+";
console.log(str.match(/[(+.]/gi));//['(', '.', '+']
可以使用 [\s\S] 或 [\d\D]匹配到所有字符包括换行符
let hd = `
qqq
ddd
`
const reg = /[\s\S]+/g;
console.log(hd.match(reg));
原子删除 h 元素
const body = document.body
const reg = /<(h[1-6])>[\s\S]*<\/\1>/g
let content = body.innerHTML.replace(reg,'')
body.innerHTML = content
- 原子组
如果一次要匹配多个元子,可以通过元子组完成
原子组与原子表的差别在于原子组一次匹配多个元子,而原子表则是匹配任意一个字符
元字符组用 () 包裹
下面使用原子组匹配 h1 标签,如果想匹配 h2 只需要把前面原子组改为 h2 即可。
原子组
const hd = `<h1>houdunren.com</h1>`;
console.log(/<(h1)>.+<\/\1>/.test(hd)); //true
邮箱验证
const email = '1212@hd.com.cn'
let reg = /^[\w-]+@([\w-]+\.)+(org|com|cc|cn)+$/
console.log('email',reg.test(email));
引用分组
在匹配时引用原子组, $n 指在替换时使用匹配的组数据。下面将标签替换为p标签
let hd = `
<h1>houdunren</h1>
<span>后盾人</span>
<h2>hdcms</h2>
`;
let reg = /<(h[1-6])>([\s\S]*)<\/\1>/gi;
console.log(hd.replace(reg, `<p>$2</p>`));