Skip to content

第十四章 RegExp

1、依赖于数组环境

2、对字符串进行增删改查

3、原始的内置查找功能是老人机,正则是智能机

js
匹配是用对象来匹配,测试是用正则来测试
3
1:正向使用
let reg = /[123]/;
let obj = "xxx"
obj.match(reg);
2:逆向使用
let reg = new RegExp("data","g");
let obj = "xxx";
reg.test(obj);

特殊考虑情况

js
1、空白
2、换行
3、大小写
4、需不需要限制范围
默认范围为一个,需不需要贪婪

基础语法

js
reg.test(data);
reg.exec(str);

srt.match(reg)



正则的重点是边界限定
总的有两种思路:
1、我要什么
2、我不要什么
js
正则范围内添上空格也会纳入!
-在原子表里为特殊字符,需要转义。
-原子表的括号是普通括号,不是原子组
-放原子表里的.和+均为普通意义的.和+

. 除换行外任意字符 普通点 无法匹配换行符

\w字母数字下划线 无法匹配特殊字符

\d数字 只有数字

\s空白 可匹配到空格,换行符,制表符

()原子组 表示一组,拥有两种编号模式:自动编号和别名编号/([1-6]) / 定义后 后续使用组名:\1

Array()里的属性:0:匹配完整 123456..原子组号和值 index:从哪里开始匹配 input:原始数组(操作的字符串) groups:组别名

[]原子表-可选-不完全匹配-多情况匹配 放里边的都匹配上去,原子表表示或的意思[123456]表示1或2或3或4或5或6 在原子表中使用^表示取反 [^]表示除了xxx都匹配

{}位数限制=>{1,2}表示1到2位

^ 以开始

$以结束 $&:匹配内容 $`:匹配内容前边的一个字符 $'匹配内容后边的一个字符

起始结束限制:^xxx$

[1-9]表示数字

[a-z]表示26个字母

[\s\S] [\d\D] 等自身+自身取反在原子表内部的 表示所有字符

/g 匹配全局,扫描到结尾

区间匹配:[0-9]只能升序,不能降序,

​ [a-z]只能升序,不能降序,

选择符:

​ | 或者 选择符左右表示整体满足一个即可

​ (大写)取反

修正符:

​ /i 不区分大小写

​ /s 视为单行,忽略换行符

​ /g 全部匹配(大文件时效率低) 显示信息较少

​ /y 全部匹配且连续满足条件,不满足立即退出

​ /m 单独当作一行处理

​ /u 匹配汉字(UTF-8) /宽字符/字节

​ 组合使用: /ig /sg /si /is


方法

js
1、字面量形式创建正则
/xxx/.test(obj) 检测obj中是否包含xxx  查找字面量
eval()将字符串转为正则=>eval(`/${variable}/`).test()
2、对象创建:
let exp = new Regexp("obj","g")  参数二为检测模式

在对象中创建正则,因为前边的参数必须为字符串,所以输入"/d"代表的是"d" 再转义也没有用。需要为"\\d"
js
字符串方法:
match
matchAll  					要求为g模式
search
replace

正则:
test()
exec

转义

当字符有多个含义,使用某个含义的时候进行转换

转义基本符号:\

+匹配一个或者多个数值

*表示匹配0个或多个

?代表0个或1个,有没有都行 表示禁止贪婪

??表示0个


字符属性与中文匹配

js
[L]具有L属性:字母
/\p{sc=Han}/gu:匹配中文
{P}匹配标点符号

lastIndex:控制开始搜索的属性(必须在/g全局模式中才会生效)
可以通过修改reg里的lastIndex值来改变
regexp.exec(str):每一个字符都获取属性
使用while((res = reg.exec(str))){
    console.log(res)
}

while (res=reg.exec(str)) arr.push(res)[1]
res[0]为原数据,所以上述方法为拷贝

表单验证

js
严格验证:/^$/

排除匹配

js
/[^abcd]/ 除了abcd都匹配

正则库

js
`匹配所有内容`/[\s\S]/

不记录组与嵌套分组

js
不记录组:
(?:xxx)   连接使用,表示不记录,即不能使用\1 $1等方法使用
xxx?      表示有没有都行


    let data = `
        https://www.bing.com
        https://bing.com
    `;
    let reg = /https:\/\/\w+\.\w+\.(com|cn|org|gov|edu)/gi;
    let reg2 = /https?:\/\/((?:\w+\.)?\w+\.(?:com|cn|gov))/gi;
    let res   = [];
    let urls = [];
    while((res = reg2.exec(data))) {
        urls.push(res[1]);
    }
    console.log(urls);

https? 表示s有没有都行

多条件验证

js
let reg = [//,//,//,//]  使用数组的形式
    
    
    const input = document.querySelector("[name='test']");
    input.addEventListener("keyup", e => {
        const value = e.target.value;
        const regs = [/^[a-z0-9]{5,10}$/i, /[A-Z]/, /[0-9]/];
        let state = regs.every(e => 
            e.test(value)
        )
        console.log(state ? "正确" : "错误");
    })

MathAll全局匹配

js
    let reg = /<(h[1-6])>([\s\S]+?)<\/\1>/gi
    let obj = document.body.innerHTML.matchAll(reg);
    let res = [];
    for (const value of obj) {
        res.push(value[2])
    }
    console.log(res)

字符串方法

js
search:搜索
let str = "";
str.search(reg) 返回索引位置

match:匹配结果

全局匹配,没有细节
单个匹配包含细节

别名

js
别名是对原子组的别名
(?<>) 				<>内部为别名,使用时即\<> $<>
 
     const data = document.querySelector("body main");
    console.log(data)
    const reg = /<a.*?href=(['"])(?<link>.*?)\1>(?<title>.*?)<\/a>/gi;
    let res = [];
    for (const iterator of data.innerHTML.matchAll(reg)) {
        res.push(iterator["groups"]);
    }
    console.log(res);

断言匹配

断言只是条件,不做内

这里的括号不是组,只是条件

结构:我要的东西+条件

js
后边是什么:		(?=)
后边不是什么:		(?!)
前边是什么:		(?<=)
前边不是什么:		(?<!)
js
    let data = "lkSIJGFLajg12356jlaksj";
    let reg = /(?<!\d+)[a-z]+/i
    let res = data.match(reg);
    console.log(res);1、零宽先行断言
简单理解:后边是什么
let reg = /obj(?=测试)/  后边为"测试"的obj
    let data = `
            js,200元,300次
            php,300.00元,100次
            node.js,180元,260次
        `;
    let reg = /(\d+)(.00)?(?=元)/gsi
    let res = data.replace(reg, (v, ...args) => {
        args[1] = args[1] || '.00';
        
        return args.splice(0,2).join('');
    })
    console.log(res)
2、零宽负向先行断言
let reg = /obj(?!测试)/  后边不是"测试"的obj
简单理解:后边不是什么
    let text = "yangzehang16102345weibo";
    let reg = /[a-z]+(?!\d)$/i
    let res = text.replace(reg,v=>{
        console.log(v)
    })

3、零宽后行断言
简单理解:前边是什么
let reg = /obj(?<=测试)/  前边为"测试"的obj

    let main = document.querySelector("main");
    const reg = /(?<=href=(['"])).+(?=\1)/gi;
    main.innerHTML  = main.innerHTML.replace(reg,(v,p)=>{
        return `https://bilibili.com`
    })
    console.log(main.innerHTML);
4、零宽负向后行断言
简单啊理解:前边不是什么
    let data = "lkSIJGFLajg12356jlaksj";
    let reg = /(?<!\d+)[a-z]+/i
    let res = data.match(reg);
    console.log(res);
js
断言模糊案例
    let phone_numbers = `
        12345678901
        09876543210
    `
    let reg = /(?<=\d{7})(\d{4})/ig;
    let res = phone_numbers.replace(reg,(v)=>{
        return "*".repeat(4);
    });
    console.log(res);
js
限制用户名关键词
   let obj = document.querySelector("[name='demo']");
   obj.addEventListener("keyup",function(){
       const reg = /^(?!.*abc.*)/i
       let status = this.value.match(reg);
       console.log(status);
   })
   console.log(obj);
js
练习
    const obj = document.querySelector("main");
    const reg = /https?:\/\/([a-z]+)?(?<!oss)\..+?/ig
    obj.innerHTML = obj.innerHTML.match(reg,v=>{
        return v
    })
    console.log(obj.innerHTML)