JS正则表达式的运用


在项目实际开发中,有时候需要对数据进行限制或模糊匹配的时候,正则可以很好的解决这些问题。

正则表达式的基础使用

正则表达式的语法:/表达式/

在javascript中,创建正则表达式的方式有两种,一是用字面量的方式创建,即let 变量名 = /表达式/,另一种是通过RegExp()构造函数的方式创建。

在检测字符串是否符合正则编写规范时,可以使用test()来检测。

let str = '123'
let reg1 = /123/
let reg2 = RegExp(/123/)
console.log(reg1.test(str)) //true
console.log(reg2.test(str)) //true
模式修饰符

模式修饰符是在正则基础表达式后面加上后缀,从而实现一些功能。

模式符 说明
g 用于在目标字符串中实现全局匹配
i 忽略大小写
m 实现多行匹配
u 以Unicode编码执行正则表达式
y 黏性匹配,仅匹配目标字符串中此正则表达式的lastIndex属性指示的索引

模式符可以根据需求多个混合使用

let str = 'abcABCD123'
let reg1 = /d/i //i忽略大小写匹配d
console.log(reg1.test(str)) //true

let str2 = '\u4e00' //一 的unicode编码是\u4e00
let reg2 = //i
console.log(reg2.test(str2)) //true

let str3 = 'abc'
let reg3 = /a/y
console.log(reg3.lastIndex) //lastIndex默认为0
console.log(reg3.test(str3)) //true
边界符
边界符 说明
^ 表示匹配行首的文本
$ 表示匹配行尾的文本

在正则中,使用^表示开始,$表示结束。

let reg = /^abc/ //表示以abc开始,之后的值无论什么都会匹配进去
console.log(reg.test('abcde')) // true
console.log(reg.test('abcdef')) // true
console.log(reg.test('dabc')) // false

let reg2 = /abc$/ //表示以abc结束,之前的值无论什么都会匹配进去
console.log(reg2.test('abcde')) // false
console.log(reg2.test('abcdef')) // false
console.log(reg2.test('dabc')) // true

let reg3 = /^abc$/ //只有内容为abc才会匹配成功
console.log(reg3.test('abcde')) // false
console.log(reg3.test('eabcd')) // false
console.log(reg3.test('abc')) // true
预定义类

预定义类是某些常见模式的简写方式,具体内容看下表。其中匹配单个字符没/表达式/g的都是从左往右第一个匹配到接下来都不再匹配

字符 含义
. 匹配除”\n”外的任何单个字符
\d 匹配所有0~9之间的任意一个数字,相当于[0-9]
\D 匹配所有0~9以外的字符,相当于[^0-9](这里的^不在//中所以不是边界符的意思)
\w 匹配任意的字母、数字和下划线,相当于[a-zA-Z0-9]
\W 匹配除所有字母、数字和下划线以外的字符,相当于[^a-zA-Z0-9]
\s 匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]
\S 匹配非空字符,相当于[^\t\r\n\v\f]
\f 匹配一个换页符( form-feed )
\b 匹配单词分节符。如”\bg”可以匹配”best grade”,结果为”g”
\B 匹配非单词分节符。如”\Bade” 可以匹配”best grade”,结果为”ade”
\t 匹配一个水平制表符
\n 匹配一个换行符
\x 匹配ISO-8859-1中的字符,如”\x61”表示”a”
\r 匹配一个回车符
\v 匹配一个垂直制表符
\u 匹配Unicode中的字符,如”一”为”\u4e00”

接下来使用match()方法来将匹配成功的结果保存到一个数组中,要是匹配失败则返回false。

//以下结果仅供参考,实际运用还得看使用场景

let str = 'abc'
let reg = /./g
console.log(str.match(reg)) //匹配结果 ['a', 'b', 'c']

let str2 = 'abc123'
let reg2 = /\d/g
console.log(str2.match(reg2)) //匹配结果 ['1', '2', '3']

let str3 = 'abc123'
let reg3 = /\D/g
console.log(str3.match(reg3)) //匹配结果 ['a', 'b', 'c']

let str4 = 'abc123'
let reg4 = /\w/g
console.log(str4.match(reg4)) //匹配结果 ['a', 'b', 'c', '1', '2', '3']

let str5 = 'abc123+-'
let reg5 = /\W/g
console.log(str5.match(reg5)) //匹配结果 ['+', '-']

let str6 = 'abc123\n\t+-'
let reg6 = /\s/g
console.log(str6.match(reg6)) //匹配结果 ['\n', '\t']

let str7 = 'abc123\n\t+-'
let reg7 = /\S/g
console.log(str7.match(reg7)) //匹配结果 ['a', 'b', 'c', '1', '2', '3', '+', '-']

let str8 = 'abc123\n\t\f+-'
let reg8 = /\f/g
console.log(str8.match(reg8)) //匹配结果只有 \f

let str9 = 'ab cd e123\n\t\f+-'
let reg9 = /\bc/g
console.log(str9.match(reg9)) //匹配结果只有 c

let str10 = 'ab cde fgh123\n\t\f+-'
let reg10 = /\Bde/g
console.log(str10.match(reg10)) //匹配结果只有 de

let str11 = 'ab cde fgh123\n\t\f+-'
let reg11 = /\t/g
console.log(str11.match(reg11)) //匹配结果只有 \t

let str12 = 'ab cde fgh123\n\t\f+-'
let reg12 = /\n/g
console.log(str12.match(reg12)) //匹配结果只有 \n

let str13 = 'ab cde fgh123\n\t\f+-'
let reg13 = /\x61/g
console.log(str13.match(reg13)) //匹配结果只有 a

let str14 = 'ab cde fgh123\n\t\f+-\r'
let reg14 = /\r/g
console.log(str14.match(reg14)) //匹配结果只有 \r

let str15 = 'ab cde fgh123\n\t\f+-\r\v'
let reg15 = /\v/g
console.log(str15.match(reg15)) //匹配结果只有 \v

let str16 = 'ab cde fgh123\n\t\f+-\r\v一'
let reg16 = /\u4e00/g
console.log(str16.match(reg16)) //匹配结果只有 一

在正则表达式中\还可以作为转义字符使用。

字符集

正则表达式中的”[]”可以实现一个字符集合,只要求匹配其中的一项,所有可供选择的字符都放在方括号内。

pattern(模式) 说明
[cat] 匹配字符集合中的任意一个字符c、 a、 t
[^cat] 匹配除c、 a、 t以外的字符
[A-Z] 匹配字母A ~ Z范围内的字符
[^a-z] 匹配字母A ~ Z范围外的字符
[a-zA-z0-9] 匹配大小写字母和0 ~ 9范围内的字符
[\u4e00-\u9fa5] 匹配任意一个中文字符(用Unicode才能实现)

在”[]”中的”^”表示取反的意思

使用了字符类就可以限定用户要输入的类型了

let reg = /[a-z]/i //这里表示只要是输入的是字母就会被获取到
str = 'abA1'
console.log(str.match(reg)) // ['a', 'b', 'A']

let reg2 = /^[^a-z]/i //这里表示开头不能为字母
console.log(reg2.test('1abc')) // true
console.log(reg2.test('A1bc')) // false
量词符

量词符用来设定某个模式出现的次数,通过使用量词符(?、+、*、{ })能够完成某个字符连续出现的匹配

字符 说明 示例 结果
? 匹配?前面的字符零次或一次 /hi?t/ 可匹配ht和hit
+ 匹配+前面的字符一次或多次 /bre+ad/ 可匹配范围从bread到bre⋯ad
* 匹配*前面的字符零次或多次 /ro*se/ 可匹配范围从rse到ro⋯se
{n} 匹配{}前面的字符n次 /hit{2}er/ 只能匹配hitter
{n,} 匹配{}前面的字符最少n次 /hit{2,}er/ 可匹配范围从hitter到hitt⋯er
{n,m} 匹配{}前面的字符最少n次,最多m次 /hit{0,2}er/ 可匹配hier、hiter和hitter三种情况

在上方表中”⋯“来表示多次。

let reg = /^hi?t/ // ? 表示 1|| 0 可以出现0次或1次
let str = 'hitt'
console.log(str.match(reg))// hit
let str2 = 'htt'
console.log(str2.match(reg))// ht

let reg2 = /^bre+ad/ // + 相当于 >= 1 可以出现1次或多次
let str3 = 'bread'
console.log(str3.match(reg2))// bread
let str4 = 'breeeeeeeead'
console.log(str4.match(reg2))// breeeeeeeead

let reg3 = /^ro*se/ // * 相当于 >=0 可以出现0次或多次
let str5 = 'rse'
console.log(str5.match(reg3))// rse
let str6 = 'rooose'
console.log(str6.match(reg3))// rooose

let reg4 = /^hit{2}er/ // {2} 就是重复t字符2次
let str7 = 'hitter'
console.log(str7.match(reg4))// hitter
let str8 = 'hiter'
console.log(str8.match(reg4))// null

通过上方例子应该就可以对量词理解不少。

括号字符

在正则表达式中,中括号”[]”表示字符集合,匹配中括号立的任意字符;

大括号”{}”表示量词符,能够完成某个字符连续出现的匹配;

小括号”()”表示优先级,被括起来的内容称为”子表达式”

接下来我们就来介绍小括号”()”

1.改变限定符的作用范围

下面我们通过代码对比使用小括号与不适用小括号的区别

//不使用小括号
let reg = /catch|er/ // |表示或的意思
let str = 'catch'
let str2 = 'er'
let str3 = 'cater'
console.log(reg.test(str)) //true
console.log(reg.test(str2)) //true
console.log(reg.test(str3)) //true

//使用小括号
let reg = /cat(ch|er)/ // |表示或的意思
let str = 'catch'
let str2 = 'er'
let str3 = 'cater'
console.log(reg.test(str)) //true
console.log(reg.test(str2)) //false
console.log(reg.test(str3)) //true
2.分组

使用小括号可以进行分组,当小括号后面有量词符时,就表示对整个组进行操作。

//不分组
let reg = /cater{2}/ //可匹配结果为caterr
let str = 'caterr'
console.log(reg.test(str)) //true

//使用小括号进行分组
let reg = /cat(er){2}/ //可匹配的结果为caterer
let str = 'caterr'
let str2 = 'caterer'
console.log(reg.test(str)) //false
console.log(reg.test(str2)) //true
3.捕获与非捕获

正则表达式中,当子表达式匹配到相应的内容时,系统会自动捕获这个匹配的行为,然后将子表达式匹配到的内容存储到系统的缓存区中,这个过程就称为”捕获“

//非捕获
let reg = /(?:J)(?:S)/ //使用(?:x)可以实现非捕获匹配
let res = 'JS'.replace(reg,'$2 $1') //$2表示reg中第二个表达式被捕获的内容 $1则表示reg中第一个表达式被捕获的内容
console.log(res) // $2 $1

//捕获
let reg = /(J)(-S)/ //使用(?:x)可以实现非捕获匹配
let res = 'JS'.replace(reg,'$2 $1') //$2表示reg中第二个表达式被捕获的内容 $1则表示reg中第一个表达式被捕获的内容
console.log(res) // JS
4.贪婪与惰性匹配

正则表达式在实现指定数量范围的任意字符匹配时,支持贪婪匹配和惰性匹配两种方式。

所谓贪婪匹配就是尽可能多的字符,惰性表示匹配尽可能少的字符。

正则匹配默认是贪婪匹配,若想要实现惰性匹配,需在上一个限定符的后面加上”?“符号

let str = 'webWEBWebwEb'
let reg1 = /w.*b/gi  //贪婪匹配
let reg2 = /w.*?b/gi //惰性匹配
console.log(reg1.exec(str)) //['webWEBWebwEb', index: 0, input: 'webWEBWebwEb', groups: undefined]
console.log(reg2.exec(str)) //['web', index: 0, input: 'webWEBWebwEb', groups: undefined]

上面代码贪婪匹配会先获取最先出现的w到最后出现的b,即可获得匹配结果为”webWEBWebwEb“。

惰性匹配时,会获取最先出现的w和最先出现的b,即可获得到匹配结果为”web“。

5.反向引用

-在编写正则表达式时,若要在正则表达式中获取存放在缓存区内的子表达式的捕获内容,则可以使用\n(n是大于0的正整数)的方式引用,这个过程就是”反向引用“。其中,”\1“表示第1个子表达式的捕获内容,”\2“表示第2个子表达式的捕获内容,以此类推。

let str = '13335 12345 56668'
let reg = /(\d)\1\1/gi //添加了()后即可通过反向引用来获取捕获的内容
console.log(str.match(reg)) //['333', '666']
6.零宽断言

零宽断言指的是一种零宽度的子表达式匹配,用于查找子表达式匹配的内容之前或子厚是否含有特定的字符集。它分为正向预查和反向预查(反向预查在ES2018后已经支持)。

正向预查:

字符 说明 示例
x(?=y) 仅当x后面紧跟着y时,才匹配x Countr(?=y|ies)用于匹配Country或Countries中的Countr
x(?!y) 仅当x后面不紧跟着y时,才匹配x Countr(?!y|lies)用于匹配Countr后不是y或lies的任意字符串中的Countr

反向预查:

字符 说明 示例
(?<=y)x 匹配紧跟y后面的x (?<=Countr)ylies用于匹配Countrylies后的ylies
(?<!y)x 不匹配紧跟y后面的x (?<!Countr)ylies用于匹配Countrylies后不为ylies的任意字符串
//正向预查
let str = 'Country'
let str2 = 'Countries'
let str3 = 'Countr'
let reg = /Countr(?=y|ies)/gi
console.log(str.match(reg)) //['Countr']
console.log(str2.match(reg)) //['Countr']
console.log(str3.match(reg)) //null 后方有y或ies才能匹配到

//反向预查
let str = 'Country'
let str2 = 'Countries'
let str3 = 'Countr'
let reg = /(?<=Countr)y|ies/gi
console.log(str.match(reg)) //['y']
console.log(str2.match(reg)) //['ies']
console.log(str3.match(reg)) //null

文章作者: LsWorld
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LsWorld !
评论
  目录