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时,才匹配xCountr(?=y|ies)用于匹配Country或Countries中的Countr
x(?!y)仅当x后面不紧跟着y时,才匹配xCountr(?!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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值