前端基础——正则表达式

正则表达式虽然看上去简单,但是在实际的前端开发时,简单的正则表达式却能够节省很大的代码量。正则表达式的功能主要式捕获、匹配。

一、基本知识

1.组成部分:

元字符,限定符号,转义字符,分组,分支条件,反义字符,后向引用。

2.在线测试网站:

  https://regex101.com/(非常好用,强烈推荐)

3.元字符:(纠正错误:\w 匹配包括下划线的任何单词字符,单词指的是“Unicode”字符集,所以不会匹配汉字

4.限定字符:

5.字符集:

6.转义字符

在书写正则表达式的时候,我们会遇到匹配特定字符的情况,这时候就需要将字符串进行转义。转义就是在需要转义的特殊字符前面加上"\"。

7.分支条件

有几种规则,只要满足其中任何一种规则都当作匹配。使用时用"|"隔开每个规则,但在实际运用的时候,需要注意分支条件的顺序,因为在匹配分支条件的时候,是按照从左到右的顺序,一旦左边有规则符合,则不会再匹配后面的规则,就相当于if-else的判断。

8.分组

使用()来进行分组,使用分组可以简化正则表达式

(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。
(?:pattern)非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)

非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

“先行断言”指的是,x只有在y前面才匹配,必须写成/x(?=y)/。比如,只匹配百分号之前的数字,要写成/\d+(?=%)/。

(?!pattern)

非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。

“先行否定断言”指的是,x只有不在y前面才匹配,必须写成/x(?!y)/。比如,只匹配不在百分号之前的数字,要写成/\d+(?!%)/

(?<=pattern)

非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。

“后行断言”正好与“先行断言”相反,x只有在y后面才匹配,必须写成/(?<=y)x/。比如,只匹配美元符号之后的数字,要写成/(?<=\$)\d+/。“后行断言”的实现,需要先匹配/(?<=y)x/x,然后再回到左边,匹配y的部分,是“先右后左”的执行顺序。

(?<!pattern)

非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。这个地方不正确,有问题。

此处用或任意一项都不能超过2位,如“(?<!95|98|NT|20)Windows正确,“(?<!95|980|NT|20)Windows 报错,若是单独使用则无限制,如(?<!2000)Windows 正确匹配。

“后行否定断言”则与“先行否定断言”相反,x只有不在y后面才匹配,必须写成/(?<!y)x/。比如,只匹配不在美元符号后面的数字,要写成/(?<!\$)\d+/

9.反义(纠正错误:\W 匹配的字符范围指的是“Unicode”字符集,所以可以匹配汉字

有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义

10.贪婪匹配与懒惰匹配

例如:

(1) a.*b——它将会匹配最长的以a开始,以b结束的字符串,如果用它来搜索aabab的话,它会匹配整个字符串aabab

(2)a.*?b——它将会匹配最短的以a开始,以b结束的字符串,如果用它来搜索aabab的话,它会匹配整个字符串aab和ab

11. 反向引用(表示连续重复字符串的情况)

       捕获组捕获到的内容,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。捕获组(Expression)在匹配成功时,会将子表达式匹配到的内容,保存到内存中一个以数字编号的组里,可以简单的认为是对一个局部变量进行了赋值,这时就可以通过反向引用方式,引用这个局部变量的值。一个捕获组(Expression)在匹配成功之前,它的内容可以是不确定的,一旦匹配成功,它的内容就确定了,反向引用的内容也就是确定的了。

      反向引用的作用通常是用来查找或限定重复、查找或限定指定标识配对出现等等。如下列例子:

连续重复的三个字母:/([a-z])\1{2}/ig

参考博文:http://www.cnblogs.com/-ShiL/archive/2012/04/06/Star201204061009.html

12.具名组匹配

在分组匹配中,获取的匹配结果不容易识别,所以在ES2018引入了具名组匹配,允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。如果具名组没有匹配成功,那么对应group的对象属性值为undefined。

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31

字符串替换时,可以使用 $<组名> 引用具名组。

let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;

'2015-01-02'.replace(re, '$<day>/$<month>/$<year>');   // '02/01/2015'

反向引用中提到可以使用数字引用(比如:\1)在正则表达式中引用分组结果,而对于具名组匹配的话,除了数字引用,可以使用:\k<组名> 的方式引用某个具名组匹配。两种语法也可以同时使用

const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false

const RE_TWICE_NUM = /^(?<word>[a-z]+)!\1$/;
RE_TWICE_NUM.test('abc!abc') // true
RE_TWICE_NUM.test('abc!ab') // false

二、使用方法

1.test

功能:对指定字符串进行一个正则表达式的匹配

语法:RegExp.test(String)

结果:返回Boolean,若匹配,则返回True;若没有匹配,则返回False

2.exec

功能:对指定的字符串进行正则表达式搜索,从左到右进行检索

语法:RegExp.exec(String)

结果:返回Array,存放匹配的结果(包含匹配的字符串,该字符串开始的下标index,完整字符串input);若没有匹配,则返回Null。当正则表达式使用 "g" 标志时,可以多次执行 exec 方法来查找同一个字符串中的成功匹配。如果正则表达式不使用 "g" 标志,无论执行多少次 exec 方法,都只会得到第一次搜索匹配的结果

3.match

功能:获取正则表达式的匹配结果

语法:String.match(RegExp)

结果:返回Array,存放匹配的结果,数组的第一个元素为整个字符串,如果正则表达式中有分组,则数组的后续会展示分组匹配的结果;若没有匹配,则返回Null

4.replace

功能:替换字符,返回

语法:String.replace(RegExp,需要的替换字符/function)

结果:返回String,是已经被替换的字符串,不会改变调用方法的字符串

【补充】如果传入的第二个参数,是函数,那么函数的参数有:match(匹配到的字符串),p1(捕获到的第一个分组)  p2(捕获到的第二个分组) ...... ,offset(匹配的字串在的原字符串中的偏移量),string(被匹配的原字符串)

5.search

功能:对指定的字符串进行正则表达式搜索

语法:String.search(RegExp)

结果:返回Number,若找到一个匹配,则返回第一个匹配的下标;若没有找到匹配,则返回-1 

四、示例

1.判定QQ电话号码在5-12位之间

Reg = /^[1-9]\d{3,10}\d$/

2.请在下列单词中找到以a开头的单词

bear alien aborb

Reg = /\ba\w*/g

3.将字符串b78se12ee567eee中的数字取出

Reg = /\d*/g

4.手机号码的验证规则

Reg = /^1(3|4|5|7|8)\d{9}$/

5.邮箱的验证规则

Reg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;

6.身份证的验证规

Reg = /^[1-9]\d{9}(0[1-9] | 1[0-2])(([0-2][1-9])|10|20|30|31)\d{3}(\d | [xX] )$/

7.截取字符串中第一个出现的英文左括号之前的字符串。比如: 北京市(海淀区)(朝阳区)(西城区),截取结果为: 北京市。

Reg=/.*?(?=\()/

8.写正则表达式,从一个字符串中提取地址,字符串如下:链接:“<a title="软件测试面试题" href="http://www.mianwww.com/html/category/it-interview/softwaretest" target="_blank">软件测试面试题</a>”。

Reg = /(?<=href=).*?(?=")/ 

9. replace的用法

// 交换字符串中的两个单词
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr); // Smith, John

 

function replacer(match, p1, p2, p3, offset, string) {
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString);  // abc - 12345 - #$*%

10. 使用正则将一串数字按照英文数字的方式表示

num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 例如:34768485 =>> 34,768,485

11.断言例子


?=匹配一个字符串,该字符串后面跟着一个特定的子字符串:

/Roger(?=Waters)/ 

/Roger(?= Waters)/.test('Roger is my dog') //false 

/Roger(?= Waters)/.test('Roger is my dog and Roger Waters is a famous musician') //true

?! 执行逆操作,匹配一个字符串,该字符串后面没有一个特定的子字符串:

/Roger(?!Waters)/

/Roger(?! Waters)/.test('Roger is my dog') //true

/Roger(?! Waters)/.test('Roger Waters is a famous musician') //false

先行断言(lookahead)使用 ?= 符号。它们已经可用了。

后行断言(lookbehind),是一个新功能,使用 ?< =

/(?<=Roger) Waters/

/(?<=Roger) Waters/.test('Pink Waters is my dog') //false

/(?<=Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //true

后行断言(lookbehind) 逆操作,使用 ?<!

/(?<!Roger) Waters/

/(?<!Roger) Waters/.test('Pink Waters is my dog') //true

/(?<!Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //false

12. 利用正则表达式把100000000转换成100.000.000

var str = "100000000000";
var reg = /\B(?=(\d{3})+$)/g;
console.log(str.replace(reg,"."));

【注】参考文档:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值