最详细 so easy 的正则表达式(二)

最详细 so easy的正则表达式(二)

朋友们可以先阅读最详细 so easy的正则表达式(一)文章链接

参考文章链接:https://blog.csdn.net/weixin_46927507/article/details/114604206


反向引用

​ 反向引用允许在正则表达式内部引用之前捕获分组匹配的文本,形式是 \num, num表示所引用分组的编号

​ 例如,匹配诸如2022-11-01这样的日期字符串,要求是需要根据前一个日期分隔符,来确定下一个日期分割符的样式,怎么做呢?

​ 这时候反向引用的重要性就来了。

(\d{4})([-:])(\d{2})\2(\d{2})

​ 啥意思呢?我们先看图,能看出什么些细节来?

在这里插入图片描述

​ 我们看分析一下这个正则表达式(\d{4})([-:])(\d{2})\2(\d{2}),其中 \2,表示所引用分组的编号为2,表示引用第二个捕获组的内容,当第一个分割符为-时,\2的内容为 -;当第一个分割符为:时,\2的内容为 :;

​ 再来看个栗子,重复字母

例14

//重复字母
//英文单词里有很多重复出现的字母, "hello shoot ..." 如想要检查某个单词中是否重复出现的字母,需要使用反向引用
let reg = /([a-z])\1/;
console.log(reg.test('aa'));//true
console.log(reg.test('bb'));//true
console.log(reg.test('ab'));//false
// \1,表示所引用分组的编号为1
// 表示引用第一个捕获组的内容,当第一个字母是什么,\1 的内容就是什么,以便达到重复字母的效果,简单说就是“你吃什么,我就吃什么”

非捕获

​ 上述提到,除了捕获分组,正则表达式还提供了非捕获分组(non-capturing group),表示方式:(?:pattern),匹配 pattern,但不捕获匹配结果(文本),也就是没有捕获分组编号,同样不可以使用反向引用,捕获分组和非捕获分组可以在同一个正则表达式中同时出现。

例15

//	有一需求,需要匹配 "iloveuiloveu" 这个字符串。
//	通过上述我们所学的内容,可以写成(iloveu){2},但是由于不需要捕获文本,只是限定量词的作用范围,所以还可以写成(?:iloveu){2}
let reg = /(iloveu){2}/;
console.log(reg.test("iloveuiloveu"));//true
console.log(RegExp.$1);//'iloveyou'

//--------------水平分割线------------------------

let reg1 = /(?:iloveu){2}/;
console.log(reg1.test("iloveuiloveu"));//true
console.log(RegExp.$1);//''

//--------------水平分割线------------------------
let reg2 = /(?:abc)\1/;
console.log(reg2.test("abcabc"));//false
let reg3 = /(abc)\1/;
console.log(reg2.test("abcabc"));//true

选择

​ 表示方式 | 竖线,以竖线 | 分隔开的多个子表达式也叫选择分支或选择项,可以理解为程序的分支结构。

​ 选择项的尝试匹配次序是从左到右,直到发现了匹配项就结束,就会忽略在于它右侧其他选择项,所有所有的子选择项都不匹配,则整个选择结构匹配失败。

​ 注意;括号 ()用来规定整个选择结构的范围,没有括号,则将整个表达式视为一个选择结构。

例16

// 对于时间匹配的分段处理
let month = /0?\d|1[0-2]/;//月(01-12)
let day = /0?\d|[12]\d|3[01]/;//日(01-31)

//思考 时 分 如何书写正则表达式? 你来试试看!

总结一下各种括号的用法

括号有很多,一般指的是 (),还有中括号 []、花括号{} ,它们长的太像了,我们一起来区分一下,上代码!

// 中括号 [] 字符集合.匹配方括号中的任意字符. 
 var reg = /^[abc]$/;
 // a 也可以 b 也可以 c 也可以  a || b || c 三选一
console.log(reg.test('a'));//true
console.log(reg.test('b'));//true
console.log(reg.test('abc'));//false
// 大括号  量词符. 里面表示重复次数
var reg1 = /^a{3}$/;
var reg2 = /^abc{3}$/;
// 它只是让c重复三次   abccc
console.log(reg2.test('abc'));//false
console.log(reg2.test('abcabcabc'));//false
console.log(reg2.test('abccc'));//true

// 小括号 表示优先级 括号里面是一个捕获组 整体看
var reg3 = /^(abc){3}$/;
// 它是让abc重复三次
console.log(reg3.test('abc'));//false
console.log(reg3.test('abcabcabc'));//true
console.log(reg3.test('abccc'));//false
console.log(RegExp.$1);//'abc'

断言

​ 正则表达式中的大多数结构匹配的文本会出现在最终的匹配结果中(一般用group(0)可以得到),但是也有些结构并不是真正匹配文本,而只负责判断在某个位置左/右侧的文本是否符合要求,这种结构被称为断言(assertion)。

​ 常见的断言有3种:单词边界、行开头结尾、环视

单词边界

​ 在文本处理中经常可能进行单词替换,比如吧一段文本中的 row 都替换成 line 。一般想到的是调用字符串的替换方法,直接替换row

替换前:The `row` we are looking for is `row` 10.
替换后:The `line` we are looking for is `line` 10.

<!-- 意想不到的结果 -->
替换前:
...`tomorrow` I will wear in `brown` standing in `row` 10 next to the rowdy guy...

替换后:...`tomorline` I will wear in `blinen` standing in `line` 10 next to the `linedy` guy...

<!-- 不仅所有单词 row 都被替换成了 line,其他单词内部的 row 也被替换成了 line,这显然不是我们想要的结果 -->

​ 解决这个问题,必须有办法确定单词 row,而不是字符串 row。为解决这类问题,正则表达式提供了专用的单词边界world boundary),记为\b。它匹配的是“单词边界”位置而不是字符。也就是说,\b能够匹配这样的位置:一边是单词字符``\w,另一边不是非单词字符\W`。

在这里插入图片描述


例17

let reg = /\bcat\b/;
console.log(reg.test("Tom is a cat"));//true
console.log(reg.test("car cat"));//true
console.log(reg.test("car"));//false
console.log(reg.test("bcat"));//false

起始位置

​ 常见的断言还有 ^$ ,分别匹配字符串的起始位置和结束位置。

​ 上述已讲,不再重复说明,忘记了的小伙伴,可以往上翻阅。


环视

​ 用于查找某些内容之前或者之后的东西,叫做环视(look around)。

javascript只支持正序环视,相当于只能往前看,不能往后看,正序环视又分为肯定正序环视否定正序环视

肯定正序环视的表示为 (?=n),表示前面必须n才匹配;(匹配任何其后紧接指定字符串 n 的字符串。)

否定正序环视的表示为 (?!n),表示前面必须不是n才匹配;

例18
let reg = /a(?=b)/;
console.log(reg.exec('abc'));//['a']
let reg1 = /a(?!b)/;
console.log(reg1.exec('abc'));//null
console.log(reg1.exec('ac'));//['a']


优先级

name从上到下优先级逐渐降低
\转义符
() (?!) (?=) []括号、字符组、环视
* + ? {n} {n,} {n,m} 量词
^ $起始结束位置
``

​ 由于括号的用途之一就是为量词限定作用范围,所以优先级比量词高。

let reg = /ab{2}/;
console.log(reg.test('abb'));//true
console.log(reg.test('abab'));//false
let reg1 = /(ab){2}/;
console.log(reg1.test('abab'));//true

//优先级
let reg2 = /^ab|cd$/;
console.log(reg2.test('abc'));//true
console.log(reg2.exec('abc'));//'ab'
let reg3 = /^(ab|cd)$/;
console.log(reg3.test('abc'));//false

补充

RegExp 构造函数属性

RegExp构造函数本身的属性被称为静态属性,会根据最后一次执行的正则表达式操作而变化。这些属性还有一个特点,就是可以通过两种不同的方式访问它们。即长属性名和短属性名(简写),简写方式大都不是有效的ECMAScript标识符,需要使用中括号语法来访问。

全名简写说明
input$_最后(最近一次)搜索的字符串(非标准特性)
lastMatch$&最后匹配的文本
lastParen$+最后匹配的捕获组(非标准特性)
leftContext$`input字符串中lastMatch之前的文本
rightContext$'input字符串中lastMatch之后的文本

例19

let reg = /(.)isoo/g;
let txt = "I love Jisoo!";
if(reg.test(txt)){
    console.log(RegExp.input);// I love Jisoo!
    console.log(RegExp.lastMatch);// Jisoo
    console.log(RegExp.lastParen);// J
    console.log(RegExp.leftContext);// I love
    console.log(RegExp.rightContext);//!
}

if(reg.test(txt)){
    console.log(RegExp.$_);// I love Jisoo!
    console.log(RegExp["$&"]);// Jisoo
    console.log(RegExp["$+"]);// J
    console.log(RegExp["$`"]);// I love
    console.log(RegExp["$'"]);//!
}

RegExp还有几个构造函数的属性,可以存储最多9个捕获组的匹配项,这些属性可以通过RegExp.$1~RegExp.$9进行访问,在调用exec()或者是test()时,这些属性会被自动填充,具体运用可以看看例10


实例方法

RegExp对象继承了Object对象的方法有toLocaleString(), toString(),valueOf()三个方法。

toLocaleString(), toString()都返回正则表达式的字面量表示。

valueOf()都返回正则表达式的本身。

例20

let reg = /(.)at/gi;
console.log(reg.toString());
console.log(reg.toLocaleString());
console.log(reg.valueOf());//返回本身 浏览器控制台输出有高亮

正则表达式篇完结啦!我认为在某些地方讲解的不是很到位,内容不够充分不够细致,主要问题在于内容的编排不够循序,下次能够改进,同时希望大家多多反馈,给予评价!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值