正则表达式的工具方法、捕获组、非捕获组、断言

常用的几种方法有:test、exec、match、matchAll、replace、replaceAll、search

1、test 匹配返回true, 不匹配false

let reg = /[\d]{1,}/g
let str = '2023年11月1日'
let currentStatus = reg.test(str)
console.log(currentStatus); // true

2、exec

(1)加g

全局模式下,exec可以多次执行。并且会在正则对象下记录 lastIndex 位置,当匹配不上时返回 null 并且 lastIndex 记录为 0。lastIndex会记录下次匹配的索引。

let reg = /[\d]{1,}/g
let str = '2023年11月1日'
let value = null
while((value = reg.exec(str)) != null) {
  console.log(value);
}

image.png

(2)不加g

只会匹配一次,和字符串上的match方法一致

3、match

(1) 加g
let reg = /[\d]{1,}/g
let str = '2023年11月1日'
let results = str.match(reg)
console.log(results); // [ '2023', '11', '1' ]
(2) 不加g
let reg2 = /[\d]{1,}/
let str2 = '2023年11月11日'
let result2 = str.match(reg2)
console.log(result2); // [ '2023', index: 0, input: '2023年11月1日', groups: undefined ]

4、matchAll

(1) 加g
let reg = /[\d]{1,}/g
let str = '2023年11月1日'
let results2 = str.matchAll(reg)
console.log(results2); // Object [RegExp String Iterator] {}
(2) 不加g,会报错提示需要添加全局符号 g
let reg = /[\d]{1,}/
let str = '2023年11月1日'
let results2 = str.matchAll(reg)
console.log(results2);
// TypeError: String.prototype.matchAll called with a non-global RegExp argument

5、replace

(1)第一个参数可以匹配 字符串 和 正则表达式
(2)第二个参数是要替换的值
a、匹配字符串,只会匹配一次
let str = '2023年11月1日'
let handStr = str.replace('年', '????')
console.log(handStr); // 2023????11月1日

let str = '2023年11年1年'
let handStr = str.replace('年', '????')
console.log(handStr); // 2023????11年1日
b、匹配正则表达式,匹配会根据正则
let reg = /[\d]{1,}/g
let str = '2023年11月1日'
let handStr = str.replace(reg, '????')
console.log(handStr); // ????年????月????日

6、replaceAll

和 replace 相似

a、匹配字符串,会全部匹配 (在ts测试项目环境下报错了 TypeError: str.replaceAll is not a function)
let str = '2023年11年1年'
let handStr = str.replaceAll('年', '????')
console.log(handStr); // 2023????11????1????
b、匹配正则表达式,和replace规则一致。

7、分组和捕获

(1)分组

对于要重复单个字符,非常简单,直接在字符后 加上限定符即可,例如 a+ 表示匹配1个或一个以上的a,a?表示匹配0个或1个a。
而多个字符进行重复,就需要用到分组了。使用小括号"()"来指定要重复的子表达式,然后对这个子表达式进行重复,例如:(abc)? 表示0个或1个abc 这里一 个括号的表达式就表示一个分组
分组可以分为两种形式,捕获组和非捕获组

a、捕获组

捕获组可以通过从左到右计算其开括号来编号 。例如,在表达式 (A)(B©) 中,存在四个这样的组:
image.png
组零始终代表整个表达式
之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用(反向引用) 在表达式中使用,也可以在匹配操作完成后从匹配器检索。

Back 引用 是说在后面的表达式中我们可以使用组的编号来引用前面的表达式所捕获到的文本序列。注意:反向引用,引用的是前面捕获组中的文本而不是正则,也就是说反向引用处匹配的文本应和前面捕获组中的文本而不是正则,也就是说反向引用处匹配的文本应和前面捕获组中的文本相同,这一点很重要!!!!

【例】([“']).*\1
其中使用了分组,\1就是对引号这个分组的引用,它匹配包含在两个引号或者两个单引号中的所有字符串,如,“abc” 或 " ’ " 或 ’ " ’ ,但是请注意,它并不会对” a’或者 'a"匹配。原因上面已经说明,Back引用只是引用文本而不是表达式。

b. 非捕获组

以 (?) 开头的组是纯的非捕获 组,它不捕获文本 ,也不针对组合计进行计数。就是说,如果小括号中以?号开头,那么这个分组就不会捕获文本,当然也不会有组的编号,因此也不存在Back 引用。

我们通过捕获组就能够得到我们想要匹配的内容了,那为什么还要有非捕获组呢?原因是捕获组捕获的内容是被存储在内存中,可供以后使用,比如反向引用就是引用的内存中存储的捕获组中捕获的内容。而非捕获组则不会捕获文本,也不会将它匹配到的内容单独分组来放到内存中。所以,使用非捕获组较使用捕获组更节省内存。在实际情况中我们要酌情选用。

b-1. 非捕获组(?:Pattern)

它的作用就是匹配Pattern字符,好处就是不捕获文本,不将匹配到的字符存储到内存中,从而节省内存。

【例1】匹配indestry或者indestries
我们可以使用indestr(y|ies)或者indestr(?:y|ies)
【例2】(?:a|A)123(?:b)
可以匹配a123b或者A123b

非捕获组有很多种形式,其中包括:零宽度断言和模式修正符

  • 零宽度断言:

image.png

(1) (?=X ) 零宽度正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。也就是说要使此零宽度断言起到我们想要的效果的话,就必须把这个非捕获组放在整个表达式的右侧。例如,/w+(?=/d) 与后跟数字的单词匹配。
(2) (?!X) 零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,/w+(?!/d) 与后不跟数字的单词匹配 。
(3) (?<=X) 零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。
(4) (?<!X) 零宽度负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配

image.png

例子: 处理数字每三位加逗号 好用!!!
/**
 * 处理字符串
 */
function thousands(num) {
  let str = num.toString()
  let reg = str.indexOf(".") > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
  return str.replace(reg, "$1,")
}

正则表达式中的预查分为四种:
1、正向肯定预查 (?=pattern) 表示的是从其当前位置开始,预测后面的字符串必须匹配上pattern
2、正向否定预查 (?!pattern) 表示的是从其当前位置开始,预测后面的字符串必须匹配不上pattern
3、反向肯定预查 (?<=pattern) 表示的是从其当前位置开始,预测前面的字符串必须匹配上pattern
4、反向否定预查 (?<!pattern) 表示的是从其当前位置开始,预测前面的字符串必须匹配不上pattern

例子:
用户名的格式为:必须有包含数字和字符,且长度在4-8位之间
^(?![0-9]+ ) ( ? ! [ a − z A − Z ] + )(?![a-zA-Z]+ )(?![azAZ]+)[0-9A-Za-z]{4,8}$

解析:
^在正则表达式中表示的是开始位置
(?![0-9]+ ) 就是一个正向否定预查,表示的是预测从开始位置到结束位置不能全都是数字。 ( ? ! [ a − z A − Z ] + )就是一个正向否定预查,表示的是预测从开始位置到结束位置不能全都是数字。 (?![a-zA-Z]+ )就是一个正向否定预查,表示的是预测从开始位置到结束位置不能全都是数字。(?![azAZ]+)也是一个正向否定预查,表示的是预测从开始位置到结束位置不能全都是字符。
可以看出,预查是不消耗字符的,也就是说预查只是限定了前面或者后面匹配的规则,而不占用匹配的字符。
经过了两个预查限制之后,后面的pattern,[0-9A-Za-z]{4,8},中括号中说明了这个位置的可选项是数字或者大小写字母,而大括号限制了其位数可以在4-8位之间,最后一个 表示了结束位置,这样就能满足要求了。注:如果仅仅 是 [ 0 − 9 A − Z a − z ] 4 , 8 表示了结束位置,这样就能满足要求了。 注:如果仅仅是^[0-9A-Za-z]{4,8} 表示了结束位置,这样就能满足要求了。注:如果仅仅[09AZaz]4,8则结果是4-8位的字母或数字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值