首页 > 其他分享 >正则表达式

正则表达式

时间:2022-12-15 12:33:30浏览次数:37  
标签:字符 匹配 断言 exec 正则表达式 规则 字符串

欢迎关注前端早茶,与广东靓仔携手共同进阶

正则表达式_字符串

前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~

一 正则表达式概述

1. 正则表达式定义

正则表达式是用来匹配一串文本中符合规则的子串的字符组合。一段用于匹配的正则表达式通常称为一个模式。JavaScript中,正则表达式可以通过字面量来定义,使用时会被包装为一个RegExp对象。

2. 正则表达式范围

一种语言对正则表达式的支持分为两个部分:

  1. 正则表达式本身的语法支持
  2. 正则表达式的运行与匹配支持,在JavaScript中,主要是RegExp对象的方法和String对象的部分方法。

用马哲的风格来讲:
第一种对语法的支持是绝对的,不以语言不同而转移,第二种运行支持是相对的,要依赖正则语法和程序语言支持。

3. 简单模式

简单模式就是直接由想要匹配的字符串组成。也仅仅能严格匹配到相等的字符串,这里区分大小写和字符顺序。


​/Str/.exec(​​​​'strStrsTR'​​​​)    ​​​​// Str​


JavaScript中,一般情况下,如果一个参数的要求是正则表达式,而实际接收到了一个字符串,那么字符串会被转化成简单模式的正则表达式。

4. 元字符概述

如果想要匹配模式更加灵活,必须依赖元字符。元字符也是一组字符串,但是不再表达本身字符的意思。元字符分可以有很多种,为方便理解,我把元字符分为下述几种:

  • 简单字符
  • 字符集
  • 量词
  • 位置
  • 文本简写字符
  • 文本控制字符

二 元字符

1. 简单字符

简单字符概述

简单匹配字符作用于单个字符上。

匹配字符

描述

​.​

匹配除了换行符外的任意单个字符

|

或运算符

\

转义运算符,用于匹配保留的字符[] () . * + ? ^ $ \ |

点号


​/./.exec(​​​​'jsx'​​​​)   ​​​​// j​


或运算符


​// exec()方法只执行一次,match方法可以通过g标志,实现全局匹配​

​'SsDdDk'​​​​.match(/s|D/g)   ​​​​// s,D,D,​


转义运算符


​/\​​​​//.exec('s//d/k')   // /,​


2. 字符集

字符集概述

字符集用于匹配集合内的所有字符。默认情况下,严格区分大小写。

字符集

描述

​[]​

字符集,匹配方括号内的任意字符,如[xyz]就是匹配x,y,z中任意一个字符

[^]

否定字符集,匹配除了方括号里的任意字符

常用字符集包括:

  • [a-z]: 匹配a-z之间任意字符,也就是匹配所有小写字母
  • ​[A-Z]​​: 匹配A-Z之间任意字符,也就是匹配所有大写字母
  • ​[0-9]​​: 匹配0-9之间任意字符,也就是匹配所有数字

字符集


​/[uH2]/.exec(​​​​'UH34'​​​​)   ​​​​// H​


否定字符集


​/[^Uh3]/.exec(​​​​'Uh23'​​​​)   ​​​​// 2​


3. 量词

量词概述

量词用于规定匹配的次数。默认情况下,每一个规则或者说元字符,仅仅匹配一次,且只作用于单个字符上。可以通过量词来描述期望的匹配次数。

量词

描述

*

匹配星号前的字符或子模式,大于等于0次。隐藏的一个问题,如果一串字符的开头不匹配,那么也不会往下继续匹配,因为规则上允许匹配0次

+

匹配加号前的字符或子模式,大于等于1次。隐藏的一个含义,如果当前没匹配到子串,就回继续查找,如果匹配到一段符合规则的子串,会继续往后,直到查到第一个不符合规则的子串的时候结束

{n}

匹配n次花括号前的字符或子模式

{n,}

匹配大于等于n次花括号前的字符或子模式

{n,m}

 匹配num个花括号前的字符,num大于等于n且小于等于m

星号


​// 匹配大于等于0个星号之前的字符或子模式。关联字符时,只关联模式串中的星号前一个字符,之前的字符会按照相应的匹配规则​

​// 第一个规则,模式串前半部分的字符是简单模式,也就是要求严格匹配​

​// 第二个规则,匹配方括号字符集里面的任意一个,​

​// 由于默认的匹配类型是贪婪匹配,因此会尽可能多的向后匹配,直到遇到不匹配的字符​

​// 第三个规则,意思为匹配a-z之间的小写字母,也就是所有的小写字母,但第二个字符是大写S,因此只匹配了第一个字符​

 

​/Sd*/.exec(​​​​'sdSdddK'​​​​)   ​​​​// Sddd​

​/[sSD]*/.exec(​​​​'sSDSkDdk'​​​​)   ​​​​// sSDS​

​/[a-z]*/.exec(​​​​'sSDSDdk'​​​​)   ​​​​// s​


加号


​// 下面的正则要求匹配一次及以上的字符d​

​// 由于加号至少要求匹配一次,因此,第一个字母不是d,不满足条件,会继续向后找,匹配到ddd​

​// ddd匹配完后,已经具备了匹配到一个子串的要求,因此,发现k不符合规则后,直接返回​

​/d+/.exec(​​​​'sdddk'​​​​)   ​​​​// ddd​


花括号


​// 匹配一次​

​/D{1}/.exec(​​​​'sDDDDk'​​​​)   ​​​​// D​

​// 匹配大于等于一次​

​/D{1,}/.exec(​​​​'sDDDDk'​​​​)   ​​​​// DDDD​

​// 大于等于1次,小于等于3次​

​/D{1,3}/.exec(​​​​'sDDDDk'​​​​)   ​​​​// DDD​


4. 位置

位置概述

位置

描述

^

匹配字符串开头

$

匹配字符串结尾

\b

匹配一个词的边界

\B

匹配一个非单词边界

如何理解边界?
一个词的边界就是不跟随其他词的字符的位置。如单词之间的空格,一行文字的开头和结尾,以及不算“字”的字符等等。
JavaScript中的“字”,或“词”,与我们日常理解的有些不同。
JavaScript中的字只包含大写字母小写字母十进制数字下划线
除此之外的字符,都可以算作打断一个单词。

位置元字符,只提供位置的约束和规则,不匹配字符。

开头


​// 匹配字符串开头的一个斜杠​

​// 斜杠是 \/匹配到的,^匹配的是位置规则。​

​/^\​​​​//.exec('//s/d/k')   // /​

​// 由于开头的字符不是/,而是s,因此匹配不到​

​/^\​​​​//.exec('s/d/k')   // null​


结尾


​// 匹配字符串结尾的一个斜杠​

​/\/$/.exec(​​​​'sd/k//'​​​​)   // /​

​// 由于结尾的字符是k,不是斜杠,因此匹配不到​

​/\/$/.exec(​​​​'sd/k'​​​​)   ​​​​// null​


边界


​// 第一个规则匹配一个在结尾边界前的字符,在这里就是b​

​/\w\b/.exec(​​​​'ab'​​​​)   ​​​​// b​

 

​// 这个规则匹配一个开始边界后的字符,在这里就是a​

​/\b\w/.exec(​​​​'a b'​​​​)   ​​​​// a​

 

​// 这个规则匹配全局匹配一个开始边界后的字符,d前有c,不是开始边界后的字符,因此没有匹配到​

​'a b-cd'​​​​.match(/\b\w/g)   ​​​​// a,b,c,​

 

​// 这段规则什么也匹配不了,因为位置元字符不匹配字符,因此,这段规则可以简化成下面的规则:​

​// \w\w,匹配两个连起来的字母,数字,下划线,但是又要求这两个字符之间存在边界,这显然是不存在的​

​/\w\b\w/.exec(​​​​'a b'​​​​)   ​​​​// null​


非边界


​// 匹配一个不是开头边界的字符,这里a是,c是,只有b不是​

​'ab-c'​​​​.match(/\B\w/g)   ​​​​// b​

 

​// 这条规则什么也匹配不到,因为之前说过,位置元字符只匹配位置,不匹配字符​

​// 不存在一个字符,既是边界,又不是边界​

​'ab-c'​​​​.match(/\b\B\w/g)   ​​​​// null​


5. 文本匹配字符

文本匹配字符

描述

\w

匹配字母,数字和下划线

\W

匹配非字母,数字和下划线

\d

匹配数字

\D

匹配非数字

\s

匹配所有空白符 相当于[\t\n\f\r\p{Z}]

\S

匹配所有非空白符


\w 和 \W​


​/\w+/.exec(​​​​'J2s_皆X'​​​​)   ​​​​// J2s_​

​/\W+/.exec(​​​​'df好卡啊z卡'​​​​)   ​​​​// 好卡啊​


​\d 和 \D​


​/\d/.exec(​​​​'g2'​​​​)   ​​​​// 2​

​/\D+/.exec(​​​​'12san4'​​​​)   ​​​​// san​


​\s 和 \S​


​/\s/.exec(​​​​'1    7   '​​​​)   ​​​​// [空格] 由于只有一个\s,因此只匹配一个空格​

​/\S+/.exec(​​​​' Jk'​​​​)   ​​​​// Jk​


6. 文本控制字符

文本控制字符

描述

\f

匹配一个换页符

\n

匹配一个换行符

\r

匹配一个回车符

\t

匹配一个制表符

\v

匹配一个垂直制表符

\p

匹配DOS命令行终止符,相当于\r\n

 

三 零宽断言

1. 零宽断言概述

普通元字符用来匹配某个特定的字符,而零宽断言用来匹配特定的_位置_,指明匹配的字符前后必定有满足断言规则的内容。它包含两个概念:

  • 断言: 即断定某件事,某种情况,必定发生。这里的断言,用来判断某个字符的前后,是否符合某种特定格式。
  • 零宽: 即不占用宽度。也就是说,断言匹配的是字符前后的位置,不占据字符。如果断言前后还有其他规则,不会跳过断言匹配的字符。断言规则在匹配结果中也不返回

注: 在断言规则的写法上,先行断言是与断言前面的模式组合,后发断言与断言后面的模式组合

2. 零宽断言种类

零宽断言

描述

​?=​

正先行断言。正,正向,理解为真,即匹配符合规则的位置,先行,即匹配断言规则前面的字符

​?!​

负先行断言。负,反向,理解为假,即匹配不符合规则的位置,先行,即匹配断言规则前面的字符

​?<=​

正,正向,理解为真,即匹配符合规则的位置,后发,即匹配断言规则后面的字符

​?<!​

负,反向,理解为假,即匹配不符合规则的位置,后发,即匹配断言规则后面的字符

3. 正先行断言


​// 正先行断言​

​// 正,正向,理解为真,即匹配符合规则的位置,先行,即匹配断言规则前面的字符​

 

​// 下面的匹配由若干数字开头,结尾是dk的字符串,再去掉断言规则本身,返回的是233​

​/\d+(?=dk)/.exec(​​​​'sdkS233dk'​​​​)   ​​​​// 233​

 

​// 下面两个例子为了验证零宽​

​// 零宽的意思是,断言不占据位置,断言规则不会过滤掉字符,​

​// 也就是说,如果匹配到了一段符合规则的子串,断言返回的子串不包含断言规则匹配的部分​

​// 但如果后续还有正则规则,会从断言规则前的位置开始​

​// 第二个返回1d,第三个返回1,可以看出,d是由\w匹配到的,因为断言本身不占据位置,所以\w从1后面的d开始匹配​

 

​/1(?=d)\w/.exec(​​​​'1d_'​​​​)   ​​​​// 1d​

​/1(?=d)/.exec(​​​​'1d_'​​​​)   ​​​​// 1​


4. 负先行断言


​// 负先行断言​

​// 负,反向,理解为假,即匹配不符合规则的位置,先行,即匹配断言规则前面的字符​

 

​// 这里的匹配规则为:前方有若干字符(字母,数字,下划线),后面跟着两个井号。​

​// 从左向右匹配,第一个不符合规则的位置为d_k2D,因为这串字符后面跟着的是K而不是##​

​// 最后,断言不匹配规则本身,因此返回的值为d_k2D​

 

​/\w+(?!​​​​##)K/.exec('##d_k2DK##$DK')   // d_k2DK​


5. 正后发断言


​// 正后发断言​

​// 正,正向,理解为真,即匹配符合规则的位置,后发,即匹配断言规则后面的字符​

 

​// 第一个规则,匹配两个井号(##)开头,后面跟若干数字的字符串,匹配结果不含井号​

​/(?<=​​​​##)\d+/.exec('1##233###4#')   // 233​

 

​// 第二个规则,匹配两个$#开头,且后续跟若干数字的字符串,​

​// 由于后发断言规则前仍有正则规则,因此前面的字符被其他的规则匹配到,返回$#233​

​/\$​​​​#(?<=\$#)\d+/.exec('1$#233###4#')   // $#233​


6. 负后发断言


​// 负后发断言​

​// 负,反向,理解为假,即匹配不符合规则的位置,后发,即匹配断言规则后面的字符​

​// 匹配一个不以两个井号开头的若干数字组成的字符串,返回45​

 

​/(?<!​​​​##)\d+/.exec('##2#45#')   // 45​


 

四 标记

1. 标记概述

标记用来修改正则表达式的一些默认行为,包括是否忽略大小写(​​i​​​),是否全局搜索(​​g​​​),是否多行搜索(​​m​​​)。
标记不属于元字符,因此不写在正则规则里面,而是写在规则后面。


​// 全局匹配所有的字母,数字,或下划线​

​/\w/g.exec(​​​​'sdk'​​​​)   ​​​​// sdk​


标记

描述

​i​

忽略大小写

​g​

全局查询搜索匹配

​m​

多行标记m可以让开头和结尾的标记符^, $在多行使用,同样的,全局匹配多次的话,需要加上全局标记g

2. 忽略大小写


​// 匹配至少两个或以上的小写字母,忽略了大小写,因此大写字母也能匹配的到​

​/[a-z]{2,}/i.exec(​​​​'sDK'​​​​)   ​​​​// sDK​


3. 全局搜索


​// 这条规则匹配若干数字,字母,或下划线,后面紧跟一个空白符,而sdk后面没有空白符,因此匹配不到​

​"s sd sdk"​​​​.match(/\w+\s/g)   ​​​​// s ,sd ,​


4. 多行匹配


​// 全局查询,且多行查询,规则要求前面若干字符,后续跟一个井号,且井号不返回​

​`​

​sdk​​​​#​

​sDK​​​​#​

​SDK!​

​`.match(/\w+(?=​​​​#)/gm)   // sdk,sDK​

 

​// 匹配到最后一个字符,并且这个字符要是井号,且多行匹配,但只匹配一次​

​`​

​sdk!​

​sDK​​​​#​

​sDK​​​​#​

​SDK@​

​`.match(/​​​​#$/m)   // #​


五 贪婪匹配和懒惰匹配

1. 概述

正则表达式默认情况下是贪婪匹配。意味着正则会尽可能地匹配多的符合规则地字符。这包含这以下几个意思:

  • 对于单个匹配字符,字符集等,不加量词的情况下,如\w,它的作用是匹配一个数字,字母,或下划线。因此,即便存在再多地字母,也只会匹配一个字母。
  • 贪婪的地方在于,会尽可能的在某一个已经匹配规则的子串后面,如果下一个字符符合规则,会继续匹配相邻的下一个字符,否则就返回现有字符。而不是会匹配到整个字符串所有符合规则的字符串(此时需要用全局标记g)。
  • 懒惰的地方在于,只匹配刚好满足规则的子串,不进行过多匹配。

2. 惰性匹配

在元字符,或者子模式后使用{{?}}将紧邻的前面的规则修饰为惰性匹配


​// 贪婪匹配​

​/\w+/.exec(​​​​'sdk_ s'​​​​)   ​​​​// sdk_​

 

​// 惰性匹配​

​/\w+?/.exec(​​​​'sdk_ s'​​​​)   ​​​​// s​


六 子模式

子模式是用括号()括起来的一组规则。子模式会被记忆下来,使用带全局标记的exec()和不带全局标记的match()匹配时会单独匹配一份。


​// 这个规则匹配一个数字后跟随多个字符,并且最后要有至少一个井号#​

​const reg = /(\d\w+)​​​​#+/g;​

​const str = ​​​​'2d3c-#5g##8ff'​​​​;​

 

​// exec()方法会将正则执行一次,如果正则给出了全局标志位g,那么返回的数据是可迭代的​

​// 可以多次运行获取后面的所有匹配结果​

​reg.exec(str);​

 

​// ["5g##", "5g", index: 6, input: "2d3c-#5g##8ff", groups: undefined]​

​// 可以看出,exec(),执行一次的返回结果的前两个数组索引处,都是匹配的结果​

​// 第一个是整个模式串匹配的结果,第二个位置是子模式单独匹配的结果​


除了exec()方法以外,子模式主要起到的就是一个分组的作用。也就是说,默认的情况下,一个修饰符或者一个量词,只修饰前面的一个字符。比如说,\w\d+这个规则要求只匹配一个字符,这个字符后面跟着至少一个数字。如果想要改成匹配字符和数字的多个组合呢?就可以使用子模式:


​'2d3f4--f6s'​​​​.match(/(\w\d)+/g)   ​​​​//  ["d3f4", "f6"]​


 

七 JavaScript中如何运行正则

JavaScript中主要使用String对象和RegExp对象提供的方法来运行正则表达式。

1. RegExp对象的方法

方法名(RegExp.prototype.)

描述

exec(string) => array

​exec()方法返回正则执行一次的结果。如果设置了全局标志g​​,会返回一个捕获组,用于迭代执行。且这个捕获组的第一项是当前完整正则的一次执行结果,第二项开始是每一个子模式的执行结果。

​test(string) => boolean​

​test()方法用于检测传入的字符串是否包含符合正则规则的子串,如果包含返回true​​,否则返回false。

2. String对象的方法

方法名(String.prototype.)

描述

​match(regex)​

​match()方法接收一个正则对象,用来匹配调用字符串中符合规则的子串。如果正则对象添加了全局标志,那么直接返回所有的匹配结果,否则,返回一个可以被迭代执行的捕获组。(同exec()​​) 。

search(reg | str) => index | -1

search()方法接收一个正则对象或一个字符串(字符串会转换成简单模式的正则表达式),用来查找调用字符串中符合规则的子串的位置,匹配到了就返回第一次出现的索引,否则返回-1

replace(reg | str, newStr | fn) => replacedStr

replace()方法接收两个参数,第一个参数是用来匹配调用字符串的正则表达式(字符串会被转化成简单模式的正则规则),第二个参数表示要替换的字符串或者返回字符串的函数。replace()方法不改变源字符串

split(reg | str, limit) => array

split()方法接收两个参数,第一个是一个正则或字符串,表示将要匹配并用于切分的字符,使用第一个参数匹配调用字符串,在符合规则的位置将字符串切分未为数组,并返回。第二个参数限制分割的片段数量。

 

欢迎关注前端早茶,与广东靓仔携手共同进阶

正则表达式_字符串

前端早茶专注前端,一起结伴同行,紧跟业界发展步伐~

 



标签:字符,匹配,断言,exec,正则表达式,规则,字符串
From: https://blog.51cto.com/feng/5939215

相关文章

  • 正则表达式匹配所有数字,包括带小数点的数字 包含限制小数位数、整数位数
    1varreg1=/^[+-]?(0|([1-9]\d*))(\.\d+)?$/;//不限制小数位数23varreg2=/^[+-]?((\d*(\.\d{1,})$)|(\d+$))/;//可限制小数位数{1,}小数时,必须1位以......
  • 正则表达式概述
    正则表达式概述什么是正则表达式正则表达式regularexpression,RE是一种字符模式,用于在查找过程中匹配指定的字符。为什么要使用正则表达式?​在工作中,我们时刻......
  • 使用CAtlRegExp正则表达式检查浮点数输入
    一、VS2008(Sp1)环境使用CAtlRegExp类需要额外下载ATLServer,(因为开源代码,没集成在VS2008里了)http://atlserver.codeplex.com/二、下载后解压,如F:\CPP\ATL_Server_S......
  • 【正则】正则表达式 自用
      JAVA的用法获取之间的字符串publicstaticvoidmain(String[]args){Stringrex="(?<=需支付:).*?(?=元)";Stringstr="您好,您需支付:250元";......
  • 正则表达式(RegExp)Note
    //RegExpvarstr=prompt()//varreg=newRegExp('a')//字面量创建正则:字面量定义正则的话两条斜线之间的任意字符都是有含义的,都会纳入到正则......
  • python 正则表达式匹配
    在python中使用正则表达式以下几个步骤,1.用importre导入正则表达式模块2.用re.compile()函数创建一个Regex对象(记得使用原始字符串)3.向Regex对象的Search()方法传入想查找......
  • 正则表达式
    前段时间人力姐姐遇到了难题,老板要求统计本月加班情况,要从飞书到处的文档中统计出每个人加班的天数和加班日期(每晚9:00之后算是加班,公司补贴30元),人工统计工作量很大,因此问我......
  • Day37:正则表达式详解
    正则表达式1.1概述正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性。比如我们在网站上输入用户账号,要求我们输入的账号信息要符合账号的格式,而校......
  • 前端开发系列034-基础篇之RegExp正则表达式
    title:'前端开发系列034-基础篇之RegExp正则表达式'tags:-javaScript系列categories:[]date:2017-09-1720:20:13本文介绍RegExp相关的知识点,包括正则表达式的......
  • Python正则表达式
    Python正则表达式情况:在一个EXCEL文件中,记录了众多公司的账目,单位有万元和亿元,彼此混杂。现想把单位统一为万元,且不显示出来法一:利用EXCEL的公式=IF(VALUE(MID(B2,1,......