JS——正则表达式

正则表达式的运用

字符串中的方法加上正则表达式威力更强,例如split、replace
对字符进行增删改查
下面通过一个小栗子,让你觉得正则表达式真香~
查找一个字符串中的所有数字,如果不用正则表达式:

let str = 'gvx543654gv3565423vgv'
//[...str]将字符串转化为数组
let nums = [...str].filter(item => Number.isNaN(parseInt(item))).join("")
// 5436543565423

使用正则表达式:

let str = 'gvx543654gv3565423vg@v'
// match:匹配
//字符串的match方法接收一个正则表达式作为参数,返回字符串由正则表达式处理过的结果
str.match(/\d/g).join("") // 5436543565423

创建正则表达式的方式:

一、字面量的形式

let str = 'gvx543654gv3565423vg@v'
// console.log(/@/.test(str)) // true 检测字符串中是否有@ ,但是这种方式中,//里不能写变量
let a = 'vg'
console.log(eval(`/${a}/`).test(str)) // true eval中的字符串可以被当作js表达式执行

二、对象的形式

let str = 'gh2667@vxv'
// let reg = new RegExp('@','g')
let a = '@'  //  \\w 字母数字下划线  \\d 数值
let reg = new RegExp(a,'g') // 对象形式的正则可以接受变量

console.log(reg.test(str)) // true 检测str中是否有@

给定一个字符串,让这个字符串随着用户的输入,相应的字母或数字变红

<body>
    <div id="changeColor">zbc123@@14</div>

    <script>
        let con = prompt("请输入要检测的内容,支持正则")
        let reg = new RegExp(con, 'g')
        let changeColor = document.getElementById('changeColor')
        changeColor.innerHTML = changeColor.innerHTML.replace(reg, search => { return `<span style="color:red">${search}</span>` })
        console.log(con) // 接到输入的值
        console.log('qe.r'.replace(/\w/g, '@')) //将'qe.r'中的字母数字下划线都替换成@
    </script>
</body>

选择符的使用

let str = 'gh2667@vxv'
// console.log(/6671|@/.test(str)) // true 判断str中是否有6671或@,满足一个条件就返回true

let num = '010-9999999'
console.log(/010|020\-\d{7,8}/.test(num))  // true
//  \d表示数字,限制数字的位数,7~8位 ,-有特殊的意义,所以我们需要转义一下,使用\转义
// 但是像上面一样写有问题,我们把9999999删掉还是返回true,改进:
console.log(/010\-\d{7,8}|020\-\d{7,8}/.test(num))  // true 左右都要完整的电话号
// 上述\-\d{7,8}是重复的,使用原子组改进:
console.log(/(010|020)\-\d{7,8}/.test(num))  // true 左右都要完整的电话号
// 上述还是不严谨,'abc010-9999999'也能匹配上,所以我们要加上限制:
num = '^010-9999999$'

原子表和原子组中的选择符

// 原子表:()   原子组:[]
let reg = /[12344]/
let str = 'h2hcbhb'
console.log(str.match(reg)) 
//[ '1', index: 1, input: 'h1hcbhb', groups: undefined ]
// 只要str中有一个符合条件就能匹配上,一个都不符合返回null
let reg2 = /(12|34)/ // 12是一个整体,34是一个整体,只有整体匹配了才能匹配
console.log(str.match(reg2)) // null  str = 'h12hcbhb'才能匹配上

转义

let price = '23.34'
// \d:0~9的数字 +:一个或多个数值
console.log(/\d+.\d+/.test(price)) // true 但是有问题,price = '23@34'还是true
// .换行外任何字符, .普通的点
console.log(/\d+\.\d+/.test(price)) // true 加了\对.进行转义  d也是普通字符串,加了\表示数值

let reg = new RegExp(/\d+\.\d+/) // true

//但是 reg = new RegExp('/\d+\.\d+/')  就不准确了,这相当于d+.d+了
reg = new RegExp('/\\d+\\.\\d+/')  // true 准确了,使用了转义
console.log(reg.test(price))

let url = "https://www.wky.com"
console.log(/https?:\/\/\w+\.\w+\.+\w/.test(url)) // ?表示有s也许无s也行,//在正则中表示边界符,所以我们用\转义就成了\/\/
//www 任何字符,我们可以使用\w ;  . 用 \.表示; wky 任何字符 \w ; . 用 \.表示;

字符边界约束

let str = 'vzx23vgf32a'
console.log(/\d/.test(str)) // true  \d代表数值 str中但凡有个数字就满足
console.log(/^\d/.test(str)) // false ^表示以数字开始; str = 3vgf就为true
console.log(/^\d$/.test(str)) // false ^表示以数字开始,$表示以数字结束; str = 2就为true

判断用户输入是否为3~6位的字母:

   <input name="user"></input>
    <span></span>
    <script>
        document.
            querySelector('[name="user"]').
            addEventListener('keyup', function () {
                // let flag = this.value.match(/[a-z]{3,6}/) // 只能输入3~6位的字母,但是有问题,只要超过3位都是成立
                let flag = this.value.match(/^[a-z]{3,6}$/) // 加上边界限制就精确判断3~6位字母了
                console.log(flag)
                document.querySelector('span').innerHTML = flag ? "正确" : "错误"
            })
    </script>

在这里插入图片描述

数值与空白元字符

let str = 'syg35dd22'
console.log(str.match(/\d/)) // [ '3', index: 3, input: 'syg35dd22', groups: undefined ]
console.log(str.match(/\d\d/)) // [ '35', index: 3, input: 'syg35dd22', groups: undefined ]
console.log(str.match(/\d\d\d/)) // null
console.log(str.match(/\d/g)) // [ '3', '5', '2', '2' ]
console.log(str.match(/\d+/g)) // [ '35', '22' ] + 匹配一个或多个
let str = '张三:120-65625556; 李四:204-62681827'
console.log(str.match(/\d{3}-\d{8}/)) // ['120-65625556', index: 3, ......]
console.log(str.match(/\d{3}-\d{8}/g)) //[ '120-65625556', '204-62681827' ]
//  \d : 数字  \D : 除了数字  + : 一个或多个
console.log(str.match(/\D/)) // [ '张', index: 0,.......]
console.log(str.match(/\D+/)) // [ '张三', index: 0,.......] 
console.log(str.match(/\D/g)) // ['张', '三', ':','-',  ';', '李', '四', ':', '-' ]
console.log(str.match(/\D+/g)) // [ '张三:', '-', ';李四:', '-' ]

 str = '张三:120-65625556; 李四:204-62681827'
//  []里写的我都要,写啥要啥
console.log(str.match(/[\d:;-]/g)) //[':', '1',  '2',  '0', '-', '6', '5',  '6',  '2',  '5', '5', '5','6',  ';', ':', '2', '0', '4', '-',  '6',  '2',  '6', '8', '1', '8',  '2',  '7']
console.log(str.match(/[\d:;-]+/g)) //[ ':120-65625556;', ':204-62681827' ]
// 在[]里写^表示方括号里写的我都不要
console.log(str.match(/[^\d:;-]+/g)) //[ '张三', '李四' ]

//   \s :空白
console.log(/\s/.test(' ')) //true
console.log(/\s/.test('\n')) //true  换行符

//    \S 除了空白
console.log(/\S/.test('tew')) //true
console.log(/\S/.test(' ')) //false
console.log(/\S/.test(' bvcx ')) //true 因为它会往后继续找,找不是空白的就返回true了

w与W元字符

//   \w : 字母、数字、下划线 也就是说他囊括了 \d
let str = 'bhbs_sd23-v21v-'
console.log(str.match(/\d+/)) // [ '23', index:7 ,........]
console.log(str.match(/\w+/)) // ['bhbs_sd23', index: 0, ........]
console.log(str.match(/\w+/g)) // [ 'bhbs_sd23', 'v21v' ]

let email = '^&%...1946376553@qq.com'
console.log(/\w+@\w+\.\w+/.test(email)) // true 这样不严谨, email = '126g%%……1946376553@qq.com'也为true
console.log(/^\w+@\w+\.\w+$/.test(email)) // false 因为加上了边界限定
//  \W : 除了数字、字母、下划线
 email = '^&%...1946376553@qq.com'
console.log(email.match(/\W+/g)) // [ '^&%...', '@', '.' ]

// 用户名需求:以字母开始,后跟字母数字下划线,用户名长度在5~10位
console.log(/^[a-z]\w{4,9}$/.test('sdr7sw')) // true 因为[a-z]已经占了一位了,所以是{4,9}

//  用户名需求:以字母开始,后跟字母数字下划线和-,不区分大小写,用户名长度在5~10位
console.log(/^[a-z][\w-]{4,9}$/i.test('sdr7sw')) // true 因为[a-z]已经占了一位了,所以是{4,9}

点元字符的使用

//  \d:数值  \w :数字字母下划线  . : 除了换行符之外的所有字符
let str = 'vsfc#%$ccsgc&v789.,.;。,'
console.log(str.match(/./)) // [ 'v', index: 0,.........]
console.log(str.match(/.+/)) // [ 'vsfc#%$ccsgc&v789.,.;。,', index: 0,inpu.....]
console.log(str.match(/.+/g)) //[ 'vsfc#%$ccsgc&v789.,.;。,' ]

// 需求:匹配一个网址
let net = 'https://www.baidu.com'
console.log(/https?:\/\/\w+\.\w+\.\w+/.test(net)) // true
//https直接写,s可有可无所以加? :直接写,//需要转义,\w+匹配一个或多个字母数字下划线,点(.)也需要转义...

// 需求:在一堆字符串中,找出里面的所有网址
net = 'https://www.baidu.com&Bbshbhttps://www.baidu.comGVV67https://www.baidu.com三个vhttps://www.baidu.com'
console.log(net.match(/https?:\/\/\w+\.\w+\.\w{0,3}/g)) // [ 'https://www.baidu.com', 'https://www.baidu.com', 'https://www.baidu.com', 'https://www.baidu.com' ]
// com只要3个字母,所以{0,3}

let str = `
vsfc#%$ccsgc
&v78-9  
`   
console.log(str.match(/.+/)) // ['vsfc#%$ccsgc', index: 1,...] 因为再遇到换行符他就停了

//  \s:把相应字符串视为单行 相当于把换行符当作普通空白字符串来使用了 这样.也能匹配换行符了 .就无敌了!!!!
console.log(str.match(/.+/s)) // ['\nvsfc#%$ccsgc\n&v78-9  \n',  index: 0,......]

let tel = '010 - 68762366'
console.log(tel.match(/\d+ - \d+/)) // ['010 - 68762366',index: 0,...]空格也是普通字符,只是我们人看不见,对计算机来说它和abc是一样的,我们可以直接写在正则中
// 但是也可以用\s来代替
console.log(tel.match(/\d+\s-\s\d+/)) // ['010 - 68762366',index: 0,...]

如何精巧的匹配所有字符

let str = 'wky'
// []:匹配str中满足[]条件的所有内容
console.log(str.match(/[sbahw]/)) // [ 'w', index: 0, inp.....]
// 不加[]表示完整的匹配一段内容
console.log(str.match(/sbahw/)) // null
let spanStr =  `
<span>
https://www.wky.com
</span>
`
// \s:空白字符 \S:除了空白字符,[\s\S] : 所有字符 [\d\D]也行
console.log(spanStr.match(/<span>[\s\S]+<\/span>/)) // [ '<span>\nhttps://www.wky.com\n</span>', index: 1, input: '\] 
console.log(spanStr.match(/<span>.+<\/span>/s))// [ '<span>\nhttps://www.wky.com\n</span>', index: 1, input: '\]

i与g模式修正符

let str = 'vzvSGfscf1F2'
console.log(str.match(/s/i)); // [ 'S', index: 3,...]  /i不区分大小写
console.log(str.match(/f/g)); //[ 'f', 'f' ]  /g全局匹配
console.log(str.match(/s/ig)); //[ 'S', 's' ]  /ig不区分大小写且全局匹配 ig gi顺序随便
console.log(str.replace(/f/ig,'@')); //vzvSG@sc@1@2  将str中的f不区分大小写全都替换成@

m多行匹配修正符

let str = `
#1 js,22元 #
#2 java,0.345yuan #
#3 python,0.21 # wky
#4 node,2301 #
`
console.log(str.match(/\s*#\d+\s+.+\s+#$/gm)); // [ '\n#1 js,22元 #', '\n#2 java,0.345yuan #', '\n#4 node,2301 #' ]
let res = str.match(/\s*#\d+\s+.+\s+#$/gm).map(item => {
    item = item.replace(/\s*#\d+\s*/, '') // js,22元 # ; java,0.345yuan ;  #node,2301 #
        .replace(/#/, '') // js,22元 ; java,0.345yuan ; node,230
    console.log(item)
    // 数组解构
    let [name, price] = item.split(',') // item.split(','):  [ 'js', '22元 ' ] ; [ 'java', '0.345yuan ' ].... ;
    return { name, price } // 对象的key和value一样,简写
})

汉字与字符属性

sc={Han}会匹配到偏旁部首 片假字

let str = `sbhhd我是中文sjb`
console.log(str.match(/\p{sc=Han}/ug)) // [ '我', '是', '中', '文' ]

lastIndex属性

let str = `sbhhd我是中文sjb`
console.log(str.match(/\w/)) // [ 's', index: 0, input: 'sbhhd我是中文sjb',...]
console.log(str.match(/\w/g)) // ['s', 'b', 'h','h', 'd', 's', 'j', 'b']属性丢失了
let reg = /\w/g // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0

console.log(reg.exec(str)) // [ 's', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'b', index: 1, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 2, input: 'sbhhd我是中文sjb',
console.log(reg.lastIndex) // 3 所以每调用一次execlastIndex就会++

while(res = reg.exec(str)){
    console.log('res: ', res);
}
// res:  [ 'h', index: 3, input: 'sbhhd我是中文sjb', groups: undefined ]
// res:  [ 'd', index: 4, input: 'sbhhd我是中文sjb', groups: undefined ]
// res:  [ 's', index: 9, input: 'sbhhd我是中文sjb', groups: undefined ]
// res:  [ 'j', index: 10, input: 'sbhhd我是中文sjb', groups: undefined ]
// res:  [ 'b', index: 11, input: 'sbhhd我是中文sjb', groups: undefined ]

有效率的y模式

g:当不是要找的值,直接跳过即可 y:得一直连续的满足条件

let str = `hhh`

let reg = /h/y // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0

console.log(reg.exec(str)) // [ 'h', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 1, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 2, input: 'sbhhd我是中文sjb',
console.log(reg.lastIndex) // 3 所以每调用一次execlastIndex就会++

 str = `hhsahd`
reg = /h/y 
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0

console.log(reg.exec(str)) // [ 'h', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 1, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // [ 'h', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.lastIndex) // 1
let str = `我的qq号:6457412145,7465111,982333225,欢迎加入,网址:jhsbbnx.com`

let reg = /(\d+),?/y // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0

console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // null
console.log(reg.lastIndex) // 0

reg.lastIndex = 6
console.log(reg.exec(str)) //['6457412145,','6457412145',index:6....]
console.log(reg.exec(str)) // ['7465111,','7465111,',index:17....]
console.log(reg.exec(str)) // ['982333225,','982333225,',index:25....]
console.log(reg.lastIndex) // 35
let str = `我的qq号:6457412145,7465111,982333225,欢迎加入,网址:jhsbbnx.com`

let reg = /(\d+),?/y // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走

reg.lastIndex = 6 //千万别忘了要设置index开始的位置,不然匹配不到,就是null,因为y要连续才有效
let arr = []
while(res = reg.exec(str)){
    console.log(res)
    arr.push(res[1])
}
console.log(arr); // [ '6457412145', '7465111', '982333225' ]

原子表基本使用

let str = `vgzs5+5sx`

let reg = /se/g // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走

console.log(str.match(reg)); // null str中要有s和e连着的字符串才得行
reg = /[se]/g //有s或e都行
console.log(str.match(reg)); // [ 's', 's' ]

let data= '2020-10-10'
reg = /\d{4}-\d{1,2}-\d{1,2}/g 
console.log(data.match(reg)); // [ '2020-10-10' ]

reg = /^\d{4}-\d{1,2}-\d{1,2}$/g // 严格以数字开头,数字结尾
console.log(data.match(reg)); // [ '2020-10-10' ]

data= '2021/10/1'
reg = /^\d{4}([-\/])\d{1,2}\1\d{1,2}$/g // 以-作为分割或者/作为分割都行,\1  : 前一个以什么分割后一个也要一样,不能出现2020-10/1的格式
console.log(data.match(reg)); // [ '2021/10/1' ]

区间匹配

let str = `2021vxfcx`

let reg = /[0-9]/g // 取到str中0-9的数 注意只能升序不能降序
console.log(str.match(reg)); // [ '2', '0', '2', '1' ]

reg = /[a-z]/
console.log(str.match(reg)); //[ 'v', index: 4,.....]
reg = /[a-z]/g
console.log(str.match(reg)); //[ 'v', 'x', 'f', 'c', 'x' ]
reg = /[a-z]+/g
console.log(str.match(reg)); //[ 'vxfcx' ]

需求:输入框中只能输入以字母开头、以字母结尾,不区分大小写,4~7位的内容

<input name="change" />

    <script>
        let input = document.querySelector(`[name="change"]`)
        input.addEventListener('keyup', function () {
            console.log(this.value.match(/^[a-z]\w{3,6}$/i))
        })
    </script>

排除匹配

let str = `2021vxfcx`
let reg = /[^vx]+/g // 除了vx其他的都匹配
console.log(str.match(reg)); // [ '2021', 'fc' ]

str = `张三:120-65625556; 李四:204-62681827`
 reg = /[^:\d-;]+/g // 除了:数字 - ;其他的都要
console.log(str.match(reg)); // [ '张三', ' 李四' ]

普通初学者容易犯的错误:
str = `(张三:120-65625556); 李四:204-62681827`
let reg = /[()]+/g // 现在的()就是普通的字符串,没有原子组的含义了,除非把它放到[]的外面,点也一样,只是普通字符串
console.log(str.match(reg)); //  [ '(', ')' ]

str = `
张三:120-65625556; 李四:204-62681827
`
let reg = /[\s\S]/g // .能匹配所有但不能匹配换行符,但/s/S真正的匹配所有
console.log(str.match(reg));// [ '\n', '张', '三', ':', '1',  '2', '0',  '-',  '6',  '5',  '6',  '2','5',  '5',  '5'...]

原子组

let str = `
<h1>vsahgvytdv</h2>
<h6>vsahgvytdv</h6>
`
let reg = /<(h[1,6])>[\s\S]*<\/\1>/gi 
// \s后面是{1,6},但是匹配的具体符号后面是[1,6],这容易混淆
// 前面有了原子表后面 才能用\1,表示和前面原子表的内容一样,
// reg = /<(h[1,6])>([\s\S])*<\/\1>/gi 也行
console.log(str.match(reg));// [ '<h6>vsahgvytdv</h6>' ]

匹配邮箱

let str = '441cdx-44981@qq.com'
console.log(str.match(/\w+\-\w+@\w+\w+\.(com|cn|org|net)/g)); //[ '441cdx-44981@qq.com' ]
console.log(str.match(/[\w-]+@[\w-]+\.(com|cn|org|net)/g)); //[ '441cdx-44981@qq.com' ]
// 但是新浪的邮箱:sggywbdvvew@sina.qq.cn的形式
str = 'sggywbdvvew@sina.qq.cn'
console.log(str.match(/[\w-]+@[\w-]+\.[\w-]+\.(com|cn|org|net)/g)); //[ 'sggywbdvvew@sina.qq.cn' ]
console.log(str.match(/[\w-]+@([\w-]+\.)+(com|cn|org|net)/g)); //[ 'sggywbdvvew@sina.qq.cn' ]

原子组引用完成替换操作

如果你某个内容要拿出来,你就把它变成一个组

let str =   `
<h1>bvxbxuy</h1>
<span>8784645</span>
<h5>bxgvsit</h5>
`
console.log(str.match(/<(h\d{1,6})>\w+<\/\1>/gi)); //[ '<h1>bvxbxuy</h1>', '<h5>bxgvsit</h5>' ]
console.log(str.replace(/<(h\d{1,6})>([\s\S]+)<\/\1>/gi,  `<p>$2</p>`)); // <p>bvxbxuy</p><span>8784645</span> <p>bxgvsit</p>
// $1 : h1、h5
// $2 : bvxbxuy、bxgvsit

let reg = /<(h\d{1,6})>([\s\S]+)<\/\1>/gi
let res = str.replace(reg, (p0, p1, p2, p3 ) => {
// p0:就是正则匹配的完整的字符串 //[ '<h1>bvxbxuy</h1>', '<h5>bxgvsit</h5>' ]
// p0 后面的参数就是原子组,p1就是 第一个(),p2就是第二个(),如果有嵌套就从第一个(开始数,嵌套在外的先数,在里的后数
    return  `<p>${p2}</p>`
}) 
console.log(res)
// <p>bvxbxuy</p> <span>8784645</span> <p>bxgvsit</p>

嵌套分组与不记录分组

let str = `https://www.baidu.com
http://wky.com
`
console.log(str.match(/https?:\/\/\w+\.\w+\.(com|cn|org)/g));
// // 需求:https:// 不要,只要域名,用括号把域名部分包起来 如下
console.log(str.match(/https?:\/\/(\w+\.\w+\.(com|cn|org))/g));
// //以上 0是整个内容 第一个出现的括号(是1,然后是2

// // 需求 去除第二个括号,让\2用不了:在括号里加(?:  如下
console.log(str.match(/https?:\/\/(\w+\.\w+\.(?:com|cn|org))/g));
// // 有些域名没有www 我们把www正则部分包起来,加? 修改正则如下
console.log(str.match(/https?:\/\/((\w+\.)?\w+\.(?:com|cn|org))/));
// ['https://www.baidu.com','www.baidu.com','www.',index: 0, input: 'ht...]
// 上面是从0开始数的,第0个表示匹配的完整的字符串,第一个是表示第一个(里匹配的内容,第二个是表示第二个(里匹配的内容 ; 所以下面while循环的时候,我们取res[1]

// 如果不想让他记录()的话,在()里加上?:即可 修改如下
console.log(str.match(/https?:\/\/((?:\w+\.)?\w+\.(?:com|cn|org))/)); // ['https://www.baidu.com','www.baidu.com',index: 0, input: 'htt...]

// 需求: 将str中所有域名都提出来
let urls = []
let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|cn|org))/g  // 不把reg提出来while循环就不会停。。。因为exec永远不会为null
while ((res = reg.exec(str))){
    urls.push(res[1])
}
console.log(urls) // [ 'www.baidu.com', 'wky.com' ]

批量使用正则完成密码验证

 <input type="text" name="userPassword" />
// 需求:密码必须以字母或数字开头,不区分大小写,密码中必须包含至少一个大写字母和一个数字
    <script>
        let input = document.querySelector(`[name="userPassword"]`)
        input.addEventListener('keyup', function (e) { // keyup:键盘抬起,mouseup鼠标抬起
            let value = e.target.value // 拿到用户输入的值
            let reg = [/^[a-z0-9]{5,7}$/i, /[A-Z]/, /\d/] // 密码必须以字母或数字开头,不区分大小写 ;密码中必须包含至少一个大写字母 ;密码中必须包含至少一个数字
            let state = reg.every(item => item.test(value)) // 字符串必须满足reg中正则的所有条件才能返回true
            console.log(state)
        })
    </script>

禁止贪婪

let str = `wkkkkky`
// +:表示一个或多个,加了问号就禁止贪婪,趋向于少的一方:一个,*:表示零个或多个,加了问号就禁止贪婪,趋向于少的一方:零个
console.log(str.match(/wk+/g)) // [ 'wkkkkk' ]
console.log(str.match(/wk+?/g)) // [ 'wk' ]
console.log(str.match(/wk*?/g)) // [ 'w' ]
console.log(str.match(/wk??/g)) // [ 'w' ] 禁止问号贪婪
console.log(str.match(/wk{2,}/g)) //[ 'wkkkkk' ]
console.log(str.match(/wk{2,}?/g)) //[ 'wkk' ] 趋向于2

禁止贪婪实践:

 <main>
        <span>vxgsffstf</span>
        <span>wky.com</span>
        <span>nbsbsc.com</span>
    </main>
    <script>
        let main = document.querySelector(`main`)
        let reg = /<span>([\s\S]+?)<\/span>/gi  // 如果不加?就会把3个span一次性匹配完,而我们需要它一次匹配一个
        main.innerHTML = main.innerHTML.replace(reg, (v, p1) => { // p1 第一个原子组所匹配的内容
            return `<h3 style="color:red">有趣-${p1}<h3>`
        })
    </script>

结果:
在这里插入图片描述
把?去掉的结果:
在这里插入图片描述

使用matchAll完成全局匹配

需求:将span标签里的内容提取出来

<body>
    <div class="main">
        <span>bhbudjsdx</span>
        <span>wky.com</span>
        <span>学正则</span>
    </div>
</body>
<script>
    const main = document.querySelector('.main')
    let reg = /<(span)>([\s\S]+?)<\/\1>/g // 这里必须加?禁止贪婪,否则匹配就会超出span之外的
    // console.log(main.innerHTML.match(reg)); //["<span>bhbudjsdx</span>\n <span>wky.com</span>\n <span>学正则</span>"]
    let res = main.innerHTML.matchAll(reg); //RegExpStringIterator {} 一个迭代对象
    let contents = []
    for (const item of res) {
        contents.push(item[2]) // 如果是item[1],content就是["span", "span", "span"]
    }
    console.log('contents: ', contents); // ["bhbudjsdx", "wky.com", "学正则"]
</script>

使用exec完成全局匹配

 const main = document.querySelector('.main')
    let reg = /<(span)>([\s\S]+?)<\/\1>/g // 这里必须加?禁止贪婪
    let contents = []
    while (res = reg.exec(main.innerHTML)) {
        contents.push(res[2])
    }
    console.log('contents: ', contents); // ["bhbudjsdx", "wky.com", "学正则"]

字符串的search和match方法

let str = `wkkkkky`
console.log(str.match(/w/g)) // [ 'w' ]
console.log(str.search(/w/g)) // 0 返回相应字符在字符串中的索引

字符串的matchAll与split

有些结果要用matchAll获得,但是有些结果使用split也行

let date = '2021/10/10'
console.log(date.split(/[-\/]/)) // [ '2021', '10', '10' ]
date = '2021-10-10'
console.log(date.split(/[-\/]/)) // [ '2021', '10', '10' ] 

$在正则替换中的使用

let num = '(010)-44444444 (020)-99999999'
let reg = /\(\d{3,4}\)-\d{7,8}/g
console.log(num.match(reg)) // [ '(010)-44444444', '(020)-99999999' ]
reg = /\((\d{3,4})\)-(\d{7,8})/g
console.log(num.replace(reg,"$1-$2"));  // 010-44444444 020-99999999

为什么写博客?

有人说最好的学习方法就是写一本书。其实,要想把知识掌握牢固,归根到底就是用起来。写书或者说写作是一种很好的以教为学的手段,写博客也一样。

持续更新…

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值