正则表达式
例子
let hd = 'afdfsdfsd123dfd4567';
// let num = [...hd].filter(item => !Number.isNaN(parseInt(item)))
// console.log(num.join(''));
console.log(hd.match(/\d/g).join(''));
字面量创建正则表达式
字面量无法操作变量,使用eval较为复杂
let hd = 'houdunren.com'
let a = 'u'
// console.log(/u/.test(hd)); // true
// console.log(/a/.test(hd)); // false
console.log(eval(`/${a}/`).test(hd)) // true
使用对象创建正则表达式
let hd = 'houdunren.com'
let a = 'u'
let reg = new RegExp(a, 'g')
console.log(reg.test(hd)); // true
<div class="content">houdunren.com</div>
<script>
let div = document.querySelector('.content')
div.innerHTML = div.innerHTML.replace(/\w/g, search => {
return `<sapn style='color: red;'>${search}</span>`
})
</script>
选择符的使用
|
// | 选择符,选择符左右两侧整个内容
console.log(/vu|&/.test(hd)); // true
let tel = '010'
let tel1 = '020'
let tel2 = '020-9999999'
let tel3 = '010-9999999'
console.log(/010|020\-\d{7,8}/.test(tel)); // true
console.log(/010|020\-\d{7,8}/.test(tel1)); // false
console.log(/010|020\-\d{7,8}/.test(tel2)); // true
console.log(/010|020\-\d{7,8}/.test(tel3)); // true
console.log(/(010|020)\-\d{7,8}/.test(tel2)); // true
console.log(/^(010|020)\-\d{7,8}$/.test(tel2)); // false ^****$完全匹配
^****$完全匹配
字符转义
转义用于改变字符的含义,用来对某个字符有多种语义时的处理。
假如有这样的场景,如果我们想通过正则查找/符号,但是 /在正则中有特殊的意义。如果写成///这会造成解析错误,所以要使用转义语法/\//来匹配。
let num = 12.34
console.log(/\d+\.\d/.test(num)); // true
let reg = new RegExp('\d\.\d', 'g')
let reg1 = new RegExp('\\d\.\\d', 'g')
console.log(reg.test(num)); // false
console.log(reg1.test(num)); // true
字符边界
使用字符边界符用于控制匹配内容的开始与结束约定。
| 边界符 | 说明 |
|---|---|
| ^ | 匹配字符串的开始 |
| $ | 匹配字符串的结束,忽略换行符 |
// 字符边界
let str = 'asfsdf3fgreg'
console.log(/^\d/.test(str));
console.log(str.match(/[a-z]{1,2}/))
let str1 = str.match(/[a-z]{1,2}/)
console.log(str1);
元字符
元字符是正则表达式中的最小元素,只代表单一(一个)字符
字符列表
| 元字符 | 说明 | 示例 |
|---|---|---|
| \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 str = 'houdunren 2010'
/**
/d 匹配任意一个数字
*/
console.log(str.match(/\d/));
console.log(str.match(/\d/g));
console.log(str.match(/\d+/g));
console.log('---------------------------');
/**
/D 与除了数字以外的任何一个字符匹配
*/
console.log(str.match(/\D/));
console.log(str.match(/\D/g));
console.log(str.match(/\D+/g));
console.log('---------------------------');
// 数值和空白元字符
let hd = `
张三: 010-99999999,李四: 020-88888888
`
console.log(hd.match(/\d{3}-\d{7,8}/));
console.log(hd.match(/\d{3}-\d{7,8}/g));
console.log('---------------------------');
/**
[^-\d:,] 除了(^) - 数字 : , \s
\s 任意一个空白字符匹配,如空格,制表符\t,换行符\n
\S 除了空白符外任意一个字符匹配
*/
console.log(hd.match(/[^-\d:,\s]+/g));
/w /W
/**
\w 与任意一个英文字母、数字或下划线匹配
*/
let str = 'houdunren2022-12_'
console.log(str.match(/\w+/));
console.log(str.match(/\w+/g));
let email = "12345678@qq.com"
let errEmail = "##@@@@12345678@qq.com"
console.log(email.match(/\w@\w/));
console.log(email.match(/\w@\w/g));
console.log(email.match(/\w+@\w+\.\w+/g));
console.log(email.match(/^\w+@\w+\.\w+$/g));
console.log(errEmail.match(/\w+@\w+\.\w+/g));
console.log(errEmail.match(/^\w+@\w+\.\w+$/g));
console.log('----------------------------------');
/**
\W 除了字母、数字或下划线外的任何字符匹配
*/
console.log('hfs_123@#$%^&'.match(/\W+/g));
/**
以字母开始,后跟字母数字下划线
[a-z] a-z的任意
^....$ 限定起始和终止
*/
let username = prompt("请输入用户名")
console.log(/[a-z]\w{4,9}/.test(username));
console.log(/^[a-z]\w{4,9}$/.test(username));
点-元字符的使用
/*
.(点):匹配除换行符外的任意字符
*/
let str = `
asdav!@#$%^&*_ /n {}><
huanhangfu
`
console.log(str.match(/.+/g));
console.log(str.match(/.+/sg)); // s为单行匹配
console.log('-----------------');
let url = "https://www.houdunren.com"
console.log(url.match(/https:\/\/\w+\.\w+.\w+/))
console.log('-----------------');
/*
空格是普通字符,匹配规则可以直接空格
\s: 任意一个空白字符匹配,如空格,制表符\t,换行符\n
*/
let tel = '010 - 99999999'
console.log(tel.match(/\d+ - \d{8}/));
console.log(tel.match(/\d+\s-\s\d{8}/));
匹配所有
可以使用 [\s\S] 或 [\d\D] 来匹配所有字符
/**
匹配所有字符
*/
let str = 'ab'
console.log(str.match(/[####b]/));
let str1 = `
<span>
dsijfisdjf @$!#%!%#%
_+
</span>
`
// [\s\S] [\d\D]
console.log(str1.match(/<span>[\d\D]+<\/span>/g));
console.log(str1.match(/<span>[\s\S]+<\/span>/g));
i与g模式修正符
把正则表达式的运行方式进行改变
正则表达式在执行时会按他们的默认执行方式进行,但有时候默认的处理方式总不能满足我们的需求,所以可以使用模式修正符更改默认方式。
| 修饰符 | 说明 |
|---|---|
| i | 不区分大小写字母的匹配 |
| g | 全局搜索所有匹配内容 |
| m | 视为多行 |
| s | 视为单行忽略换行符,使用. 可以匹配所有字符 |
| y | 从 regexp.lastIndex 开始匹配 |
| u | 正确处理四个字符的 UTF-16 编码 |
i
将所有houdunren.com 统一为小写
g
使用 g 修饰符可以全局操作内容
let str = 'hoUdunren'
console.log(str.match(/u/));
console.log(str.match(/u/i));
console.log(str.match(/u/ig));
console.log(str.replace(/u/gi, '$'));
m
用于将内容视为多行匹配,主要是对 ^和 $ 的修饰
let str = `
#1 js,200元 #
#2 php,300元 #
#3 mysql.com # 数据库
#4 node.js,200元 #
`
// [{ name: 'js', price: '200元'}]
/**
* 0->
*/
console.log(str.match(/\s*#\d+\s+.+\s+#\s+/g));
/**
m: 每一行单独对待
*/
console.log(str.match(/^\s*#\d+\s+.+\s+#$/gm));
let lessons = str.match(/^\s*#\d+\s+.+\s+#$/gm).map(v => {
v = v.replace(/\s*#\d+\s*/, '').replace(/#/, '')
// console.log(v.split(','))
let [name, price] = v.split(',')
return {name, price}
})
console.log(JSON.stringify(lessons, null, 2))
汉字与字符属性
u
-
每个字符都有属性,如
L属性表示是字母,P表示标点符号,需要结合u模式才有效。其他属性简写可以访问 属性的别名网站查看。 -
字符也有unicode文字系统属性
Script=文字系统,下面是使用\p{sc=Han}获取中文字符han为中文系统,其他语言请查看 文字语言表
let hd = 'houdunren2010.好好学习天天向上'
// 使用\p{L}属性匹配字母
console.log(hd.match(/\p{L}/gu));
//使用\p{P}属性匹配标点
console.log(hd.match(/\p{P}+/gu));
// 匹配中文
console.log(hd.match(/\p{sc=Han}+/gu));
let str = "𝒳𝒴";
console.log(str.match(/[𝒳𝒴]/gu));
lastIndex
RegExp对象lastIndex 属性可以返回或者设置正则表达式开始匹配的位置
- 必须结合
g修饰符使用 - 对
exec方法有效 - 匹配完成时,
lastIndex会被重置为0
let hd = 'houdunren.js'
console.log(hd.match(/\w/));
console.log(hd.match(/\w/g));
let reg = /\w/g
console.log(reg.lastIndex);
console.log(reg.exec(hd));
console.log(reg.lastIndex);
console.log(reg.exec(hd));
console.log(reg.exec(hd));
console.log(reg.exec(hd));
let hd = 'houdunren.js'
console.log(hd.match(/\w/));
console.log(hd.match(/\w/g));
let reg = /\w/g; // 全局模式下会记录上一次搜索的位置
while( res = reg.exec(hd)){
console.log(res);
}
y
let hd = 'udunren'
// g会忽略不符合的内容
let reg = /u/g
console.log(reg.exec(hd));
console.log(reg.lastIndex);
console.log(reg.exec(hd));
console.log(reg.lastIndex);
console.log(reg.exec(hd));
console.log(reg.lastIndex);
console.log('---------------------------------');
// y不会忽略不符合的内容
let reg1 = /u/y
console.log(reg1.exec(hd));
console.log(reg1.lastIndex);
console.log(reg1.exec(hd));
console.log(reg1.lastIndex);
console.log(reg1.exec(hd));
console.log(reg1.lastIndex);
let hd = `后盾人QQ群:11111111,999999999,88888888
后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
let reg = /(\d+),?/y
reg.lastIndex = 7
console.log(reg.exec(hd));
console.log(reg.exec(hd));
console.log(reg.exec(hd));
console.log(reg.exec(hd));
let hd = `后盾人QQ群:11111111,999999999,88888888
后盾人不断分享视频教程,后盾人网址是 houdunren.com`;
let reg = /(\d+),?/y
reg.lastIndex = 7
let qq = []
while (res = reg.exec(hd)) qq.push(res[1])
console.log(qq); // ['11111111', '999999999', '88888888']
原子表
原子表
在一组字符中匹配某个元字符,在正则表达式中通过元字符表来完成,就是放到[] (方括号)中。
使用语法
| 原子表 | 说明 |
|---|---|
| [] | 只匹配其中的一个原子 |
| [^] | 只匹配"除了"其中字符的任意一个原子 |
| [0-9] | 匹配0-9任何一个数字 |
| [a-z] | 匹配小写a-z任何一个字母 |
| [A-Z] | 匹配大写A-Z任何一个字母 |
let hd = 'houdunren'
console.log(hd.match(/ue/))
console.log(hd.match(/[ue]/g))
let tel = '2022-02-23'
let reg = /^\d{4}-\d{2}-\d{2}$/
console.log(tel.match(reg));
let tel1 = '2022/02/22'
let tel2 = '2022/02-22'
let reg1 = /^\d{4}[-\/]\d{2}[-\/]\d{2}$/
console.log(tel1.match(reg1));
console.log(tel2.match(reg1));
let reg2 = /^\d{4}([-\/])一一对应\d{2}\1\d{2}$/ // \1与([-\/])一一对应
console.log(tel2.match(reg2));
console.log(tel1.match(reg2));
区间匹配、排除匹配
let hd = 'houdunren345234'
/**
[] 原子表里只是代表一个字符
原子表里面的内容只能是升序,不能是降序
*/
console.log(hd.match(/[a-z]+/g));
console.log(hd.match(/[0-9]+/g));
console.log('----------------------');
/**
[^....] 原子表中的^表示除了原子表中的内容都要匹配
*/
let str = 'houdunren.com'
console.log(str.match(/[^ue]/gi));
let hd1 = `
张三: 010-99999999,李四: 020-88888888
`
console.log(hd1.match(/[^\d:\-,]+/g));
原子表字符不解析
let hd = '(houdunren).+'
console.log(hd.match(/[()]/gi));
// console.log(hd.match(/()/gi));
console.log(hd.match(/[.+]/gi)) // [] 内匹配 点 / 加号
console.log(hd.match(/.+/gi)) // 原字符(点:匹配除换行符外的任意字符)
使用原子表匹配所有内容
let hd = `
houdunren
hdcms
`
console.log(hd.match(/.+/gs));
// [\s\S] \s 空白和 \S除了空白 == 所有
// [\d\D] 所有内容
console.log(hd.match(/[\d\D]/g));
正则操作DOM元素
<p>后盾人</p>
<h1>houdunren.com
hhhhhhhhfffff
</h1>
<h3></h3>
<h2>hdcmd.com</h2>
<script>
let body = document.body
let reg = /<(h[1-6])>.+<\/\1>/gi;
// body.innerHTML = body.innerHTML.replace(reg, '')
let reg1 = /<(h[1-6])>[\s\S]*<\/\1>/gi;
body.innerHTML = body.innerHTML.replace(reg1, '')
</script>
原子组
()括号包住的:原子组
// ()括号包住的:原子组
let hd = `
<h1>feichichengzhang</h1>
<h2>lishanglong</h2>
`
let reg = /<h[1-6]>[\s\S]*<\/h[1-6]>/ig // 前面的标签无法和后面的标签保持一致
/**
需要保持一致就要使用(),让其成组
() 成组,获取就是 \1 \2...
*/
let reg1 = /<(h[1-6])>[\s\S]*<\/\1>/ig // 标签的闭合标签有个/需要使用\转义
console.dir(hd.match(reg1))
let reg2 = /<(h[1-6])>([\s\S]*)<\/\1>/i // 标签的闭合标签有个/需要使用\转义
console.dir(hd.match(reg2))
邮箱验证中原子组的使用
<input type="text" name="mail" value="12345678@qq.com.cn">
<script>
let mail = document.querySelector(`[name="mail"]`).value
let reg0 = /^[\w-]+@[\w-]+\.(com|org|cc|cn|net)$/i
let reg = /^[\w-]+@([\w-]+\.)+(com|org|cc|cn|net)$/i
console.log(mail.match(reg));
</script>
原子组引用完成替换操作
let hd = `
<h1>houdunren</h1>
<span>好好学习</span>
<h2>study</h2>
`
/**
1.标签的闭合标签有个/需要使用\转义
2.需要保持一致就要使用(),让其成组
() 成组,获取就是 \1 \2...
3.replace,p0为所有字符,p1-pn为所有的原子组
*/
let reg = /<(h[1-6])>(\w[\s\S]+)<\/\1>/gi;
let res = hd.replace(reg, (p0, p1, p2, p3) => `<p>${p2}</p>`)
console.log(res);
1.嵌套分组与不记录组
let hd = `
https://www.houdunren.com
http://houdunwang.com
https://baidu.com
`
// 正则匹配域名
// 不记录分组
// let reg = /https:\/\/(\w+\.\w+\.(com|org|cn))/i
// let reg = /https:\/\/(\w+\.\w+\.(?:com|org|cn))/i
/**
原子组按从左到右的顺序
第一个原子组 (\w+\.\w+\.(com|org|cn))
第二个原子组 (com|org|cn)
原子组前面加 ?: 忽略这个原子组
*/
let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|org|cn))/ig
/**
? 零次或一次
原子组按从左到右的顺序
第一个原子组 (?:\w+\.)?\w+\.(?:com|org|cn)
第二个原子组 (?:\w+\.)
第三个原子组 (?:com|org|cn)
原子组前面加 ?: 忽略记录这个原子组
*/
// console.dir(hd.match(reg));
// console.dir(reg.exec(hd))
// console.dir(reg.lastIndex)
// console.dir(reg.exec(hd))
// console.dir(reg.lastIndex)
// console.dir(reg.exec(hd))
// console.dir(reg.lastIndex)
// console.dir(reg.exec(hd))
// console.dir(reg.lastIndex)
let urls = []
while((res = reg.exec(hd))){
// console.log(res[1]);
urls.push(res[1])
}
console.log(urls) // ['www.houdunren.com', 'houdunwang.com', 'baidu.com']
多种重复匹配基本使用
基本使用
如果要重复匹配一些内容时我们要使用重复匹配修饰符,包括以下几种。
| 符号 | 说明 |
|---|---|
| * | 重复零次或更多次 |
| + | 重复一次或更多次 |
| ? | 重复零次或一次 |
| {n} | 重复n次 |
| {n,} | 重复n次或更多次 |
| {n,m} | 重复n到m次 |
因为正则
最小单位是元字符,而我们很少只匹配一个元字符如a、b所以基本上重复匹配在每条正则语句中都是必用到的内容。
/**
贪婪匹配
+ 一个或多个
* 0个或多个
{} 限定数量
? 0或1
*/
let hd = 'hdddddddddddd'
console.log(hd.match(/hd+/));
console.log(hd.match(/hd*/));
console.log(hd.match(/hd{1,3}/)); // 1-3
console.log(hd.match(/hd{1,}/)); // 1->无限
console.log(hd.match(/hd?/)); // 1->无限
重复匹配与原子组影响与电话号码正则
let hd = 'hdddddddddddddddddddddhdh'
console.log(hd.match(/hd+/));
console.log(hd.match(/(hd)+/));
let tel = '010-99999999'
console.log(tel.match(/^0\d{2,3}-\d{7,8}$/));
网站用户名验证
<input type="text" name="username">
<script>
document.querySelector(`[name='username']`).addEventListener('keyup', (e)=>{
const value = e.target.value;
let reg = /^[a-z][\w-]{2,7}$/i
console.log(reg.test(value));
})
</script>
批量使用正则完成密码验证
<input type="text" name="password">
<script>
let input = document.querySelector(`[name='password']`)
input.addEventListener('keyup', (e) => {
let value = e.target.value
console.log(value)
let regs = [/^[a-z0-9]{5,10}$/i, /[A-Z]/, /[0-9]/]
let state = regs.every(e => e.test(value))
console.log(state ? '正确' : '密码错误');
})
</script>
禁止贪婪
贪婪匹配+? 只获取最少的
let hd = 'hdddd'
console.log(hd.match(/hd+/));
/**
贪婪匹配+? 只获取最少的
*/
console.log(hd.match(/hd+?/));
console.log(hd.match(/hd*?/));
console.log(hd.match(/hd{2,}?/));
标签替换的禁止贪恋使用
<main>
<span>houdunrenwang</span>
<span>hdcms</span>
<span>houdunren.com</span>
</main>
<script>
/*span -> h4,描红 文字前加 后盾-*/
const main = document.querySelector('main')
// let reg = /<span>[\s\S]+<\/span>/ig // +:贪婪,会把所有匹配
// let reg = /<span>[\s\S]+?<\/span>/ig
let reg = /<span>([\s\S]+?)<\/span>/ig
main.innerHTML = main.innerHTML.replace(reg, (v, p1) => {
console.log(v);
return `<h4 style="color:red;">后盾人-${p1}</h4>`
})
</script>
使用matchAll完成全局匹配
<h1>houdunren.com</h1>
<h2>hdcms.com</h2>
<h1>后盾人</h1>
<script>
// 全局匹配标签内的内容
// let reg = /<(h[1-6])>([\s\S]+?)<\/\1>/i // 一个内容,非全局
let reg = /<(h[1-6])>([\s\S]+?)<\/\1>/ig
const body = document.body;
// console.dir(body.innerHTML.match(reg))
/**
matchAll
得到的是一个迭代对象
这个迭代对象可以遍历
*/
// console.dir(body.innerHTML.matchAll(reg))
const hd = body.innerHTML.matchAll(reg)
const contents = []
for(const iterator of hd) {
// console.dir(iterator)
contents.push(iterator[2])
}
console.log(contents); // ['houdunren.com', 'hdcms.com', '后盾人']
为低端浏览器定义原型方法matchAll
<h1>houdunren.com</h1>
<h2>hdcms.com</h2>
<h1>后盾人</h1>
<script>
// matchAll
/**
matchAll
低端浏览器中没有这个方法
*/
String.prototype.matchAll = function(reg) {
let res = this.match(reg)
if(res){
let str = this.replace(res[0], '^'.repeat(res[0].length))
let match = str.matchAll(reg) || []
return [res, ...match]
}
}
let hd = 'houdunren';
// console.log(hd.matchAll(/u/i));
// console.log(hd.matchAll(/(u)/i));
let body = document.body;
let search = body.innerHTML.matchAll(/<(h[1-6])>([\s\S]+?)<\/\1>/)
console.log(search);
使用exec完成全局匹配
let hd = 'houdunren'
let reg = /u/gi
console.log(reg.exec(hd));
console.log(reg.lastIndex);
console.log(reg.exec(hd)); // 会接着上一个的匹配往下,因为lastIndex,直到匹配不到为0
console.log(reg.lastIndex);
<h1>houdunren.com</h1>
<h2>hdcms.com</h2>
<h1>后盾人</h1>
<script>
// let hd = 'houdunren'
// let reg = /u/gi
// let result = []
// while(res = reg.exec(hd)) {
// result.push(res)
// }
// console.log(result);
function search(string, reg) {
let result = []
while (res = reg.exec(string)) {
result.push(res)
}
return result
}
let matchs = search(document.body.innerHTML,/<(h[1-6])>([\s\S]+?)<\/\1>/gi)
console.log(matchs);
</script>
字符方法
下面介绍的方法是 String 提供的支持正则表达式的方法
- search
- match
- matchAll
- split
- replace
search、match
search() 方法用于检索字符串中指定的子字符串,也可以使用正则表达式搜索,返回值为索引位置
/**
match
exec
matchAll
replace
*/
// search 搜索
let hd = "houdunren.com"
console.log(hd.search('h'));
console.log(hd.search(/u/));
// match 匹配结果
console.log(hd.match(/u/i));
console.log(hd.match(/u/gi));
let hd1 = `
https://www.houdunren.com
http://houdunwang.com
https://www.sina.com.cn
`
// 网址匹配
// let reg = /https?:\/\/(\w+\.)?\w+(\.(com|reg|org))+/gi
let reg = /https?:\/\/(\w+\.)?(\w+\.)+(com|cn|org|cc)/gi
console.log(hd1.match(reg));
matchAll
let hd1 = `
https://www.houdunren.com
http://houdunwang.com
https://www.sina.com.cn
`
// 网址匹配
let reg = /https?:\/\/(?:\w+\.)?(\w+\.)+(?:com|cn|org|cc)/gi
console.log(hd1.matchAll(reg));
for (const iterator of hd1.matchAll(reg)) {
console.log(iterator);
}
split
let hd = '2020-09-12'
console.log(hd.split("-"));
console.log(hd.split(/[-\/]/)); // ['2020', '09', '12']
replace
let date = '2030/12/18'
// 替换+正则
date.replace(/\//g, '-')
let Tel = "(010)99999999 (020)88888888"
// 010-999999999
let reg = /\((\d{3,4})\)(\d{7,8})/g
console.log(Tel.match(reg)); // ['(010)99999999', '(020)88888888']
/*
\( 普通字符(
$1 原子组一
$2 原子组二
*/
console.log(Tel.replace(reg, '$1-$2')); // 010-99999999 020-88888888
$& 符在正则替换中的使用
/**
$`(反引号)匹配内容前面的内容
$'(引号) 匹配内容后面的内容
$& 匹配到的内容
*/
let hd = "=后盾人$"
console.log(hd.replace(/后盾人/, "$&"));
console.log(hd.replace(/后盾人/, "$`"));
console.log(hd.replace(/后盾人/, "$'"));
console.log(hd.replace(/后盾人/, "$`$`$&$'$'"));
<main>在线教育是一种高效的学习方式,教育是一生的事业</main>
<script>
const main = document.querySelector('body main')
main.innerHTML = main.innerHTML.replace(/教育/g, `<a href="https:www.baidu.com">$&</a>`)
</script>
原子组
原子组在替换中的使用技巧
<main>
<a style="color: red;" href="http://www.baidu.com">百度</a>
<a href="http://houdunren.com">后盾人</a>
<a href="http://yahoo.com">雅虎</a>
<h4>http://www/hdcms.com</h4>
</main>
<script>
const main = document.querySelector('body main')
const reg = /(<a.*href=['"])(http)(:\/\/)(www\.)?(hdcms|houdunren)/i
main.innerHTML = main.innerHTML.replace(reg, (v, ...args) => {
console.log('all', args);
args[1] += 's'
args[3] = args[3] || 'www.'
// console.log(args.splice(0, 5).join);
return args.splice(0, 5).join('')
})
</script>
原子组别名
原子组()的最前面使用
?<别名>
let hd = `
<h1>houdunren.com</h1>
<span>hdcms.com</span>
<h1>后盾人</h1>
`
// const reg = /<(h[1-6])>(.*?)<\/\1>/gi
const reg = /<(h[1-6])>(?<con>.*?)<\/\1>/gi
// hd.replace(reg, '<h4>$2</h4>')
hd.replace(reg, '<h4>$<con></h4>')
使用原子组别名优化正则
<main>
<a href="http://www.baidu.com">百度</a>
<a href="http://houdunren.com">后盾人</a>
<a href="http://yahoo.com">雅虎</a>
</main>
<script>
// [{link:'',title:''}]
const main = document.querySelector('body main')
const reg = /<a.*?href=(['"])(?<link>.*)\1>(?<title>.*?)<\/a>/i
// console.log(main.innerHTML.match(reg));
const links = []
for (const iterator of main.innerHTML.match(reg)) {
console.log(iterator['groups']);
links.push(iterator['groups'])
}
console.log(links);
</script>
正则方法
正则方法test
<input type="text" name="email">
<script>
const email = document.querySelector(`[name='email']`)
email.addEventListener('keyup', (e) => {
let value = e.target.value;
let flag = /^[\w-]+@(\w+\.)+(com|org|cn)$/i.test(value)
console.log(flag);
})
</script>
正则方法exec
不使用 g 修饰符时与 match 方法使用相似,使用 g 修饰符后可以循环调用直到全部匹配完。
- 使用
g修饰符多次操作时使用同一个正则,即把正则定义为变量使用 - 使用
g修饰符最后匹配不到时返回null
// 计算内容中后盾人出现的次数
<main>后盾人不断分享视频教程,后盾人网址是 houdunren.com</main>
<script>
let reg = /后盾人/g
const main = document.querySelector('body main')
let count = 0;
while(res = reg.exec(main.innerHTML)){
count++
}
console.log(count);
</script>
断言匹配
零宽先行断言
后面是什么
(?=exp)
零宽先行断言 ?=exp 匹配后面为 exp 的内容
<main>后盾人不断分享视频教程,后盾人网址是 houdunren.com</main>
<script>
// 给后面接有网址的后盾人加上a标签
let main = document.querySelector('body main')
/**
匹配内容(?=xxx) 匹配的内容后面是xxx的内容
*/
let reg = /后盾人(?=网址)/g;
/***
$& 自身内容
*/
main.innerHTML = main.innerHTML.replace(reg, `<a href="https://houdunren.com">$&</a>`)
</script>
// 使用断言规范价格
let lessons = `
js,200元,300次
php,300.00元,100次
node.js,180元,260次
`
let reg = /(\d+)(.00)?(?=元)/gi
/**
可先将所有的内容获取,去判断 .00原子组是否存在
第一个原子组 (/d+)
第二个原子组 (.00)
(?=exp) 这个不是原子组
*/
lessons = lessons.replace(reg, (v, ...args) => {
// console.log(args);
args[1] = args[1] || '.00'
return args.splice(0, 2).join('')
});
console.log(lessons);
零宽后行断言
前面是什么
(?<=exp)
零宽后行断言 ?<=exp 匹配前面为 exp 的内容
// 修改链接
<a href="https://baidu.com">百度</a>
<a href="https://yahoo.com">雅虎</a>
<script>
// let hd = 'houdunren789hdcms666'
// const reg = /(?<=houdunren)\d+/gi
// console.log(hd.match(reg));
let reg = /(?<=href=(['"])).+(?=\1)/gi
let body = document.body
body.innerHTML = body.innerHTML.replace(reg, `htts://houdunren.com`)
</script>
使用断言模糊电话号
let users = `
向军电话: 12345678901
后盾人电话:98745675603
`
/*
断言只是条件,不在匹配当中
*/
let reg = /(?<=\d{7})\d{4}/gi;
console.log(users.replace(reg, '****'));
零宽负向先行断言
后面不是什么
(?!exp)
零宽负向先行断言 后面不能出现 exp 指定的内容
// ?= ?!
let hd = "houdunren2010hscms"
let reg0 = /[a-z]+(?!\d+)/gi;
console.log(hd.match(reg0)); // ['houdunre', 'hscms']
let reg = /[a-z]+(?!\d+)$/gi; // $限制[a-z] 表示以字母结尾
console.log(hd.match(reg)); // ['hscms']
断言限制用户名关键词
// 断言限制用户名关键词
const input = document.querySelector(`[name='username']`)
input.addEventListener('keyup', function(){
// 不能包含向军
const reg = /^(?!.*向军)[a-z]{5,6}*$/i
console.log(this.value.match(reg));
})
零宽负向后行断言
前面不是什么
(?<!exp)
零宽负向后行断言 前面不能出现exp指定的内容
let hd = 'hdcms090houdunren'
let reg = /(?<!\d+)[a-z]+/gi
console.log(hd.match(reg)); // ['hdcms', 'oudunren']
let reg1 = /^(?<!\d+)[a-z]+/gi // ^限定【a-z】
console.log(hd.match(reg1)); // ['hdcms']
<main>
<a href="https://www.houdunren.com/1.jpg">1.jpg</a>
<a href="https://oss.houdunren.com/2.jpg">2.jpg</a>
<a href="https://cdn.houdunren.com/3.jpg">3.jpg</a>
<a href="https://houdunren.com/2.jpg">后盾人</a>
</main>
<script>
const main = document.querySelector('main')
let reg = /https:\/\/([a-z]+)?(?<!oss)\..+?(?=\/)/gi
main.innerHTML = main.innerHTML.replace(reg, v =>{
console.log(v);
return 'https://oss.houdunren.com'
})
</script>
学习笔记,来源后盾人