当前位置: 首页 > 科技观察

正则表达式完全指南

时间:2023-03-22 15:38:59 科技观察

正则表达式是一个比较强大的字符串匹配、字符串查找、字符串替换等操作工具。立即了解JavaScript中的正则表达式!一、基本概念正则表达式(regularexpressions,在代码中常简称为regex、regexp或RE)使用单个字符串来描述和匹配一系列满足一定语法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换。它将搜索模式定义为字符序列。正则表达式有很多用途,例如:表单输入验证。搜索和替换。过滤日志等大型文本文件中的信息。读取配置文件。网页抓取。使用具有一致语法的文本文件,例如CSV。正则表达式的语法如下:/Regularexpressionbody/Modifier(optional)首先看一个基本的正则表达式:/at/,它只匹配字符串“at”中的第一个“:这里,主要正则表达式的主体是“at”,不使用修饰符,后面会介绍正则表达式的修饰符2.创建方法正则表达式的创建有两种方式:字面量:正则表达式直接放在//:constrex=/pattern/;constructor:RegExp对象代表一个正则表达式例子:constrex=newRegExp("pattern");这两种方法的一个很大的区别是对象的构造函数允许传递带引号的表达式,这样就可以动态创建正则表达式了,这两种方法创建的Regex对象的方法和属性都是一样的:letRegExp1=/a|b/letRegExp2=newRegExp('a|b')console.log(RegExp1)//输出:/a|b/console.log(RegExp2)//输出结果:/a|b/3.模式匹配关于正则表达式最复杂的部分是如何编写正则表达式。让我们看看如何编写正则表达式。1、字符集我们要匹配bat、cat、fat的字符串怎么办?您可以通过使用一个字符集来做到这一点,用[]表示,它将匹配包含的任何一个字符。这里可以使用/[bcf]at/ig:可以看到这里匹配到了字符串中的bat、cat、fat。因为我们使用了g修饰符,所以匹配了三个。当然也可以使用字符集来匹配数字:2.字符范围如果我们要匹配一个字符串中所有以at结尾的单词,最直接的方法就是使用一个字符集,提供其中的所有字母。对于范围内的此类字符,可以直接定义字符范围,用-表示。用于匹配指定范围内的任意字符。这里可以使用/[a-z]at/ig。如您所见,正则表达式符合我们的预期。范围的常用用法如下:partialrange:[a-f],匹配a到f的任意字符。小写范围:[a-z],匹配从a到z的任意字符。大写范围:[A-Z],匹配A到Z任意字符。数字范围:[0-9],匹配0到9任意字符。符号范围:[#$%&@]。混合范围:[a-zA-Z0-9],匹配所有数字,大小写字母中的任意字符。3.字符个数如果要匹配三个字母的单词,根据我们上面学习的字符范围,可以这样写:[a-z][a-z][a-z]这里我们匹配三个字母的单词,那么如果你想要匹配10个、20个字母的单词呢?有必要一一写scope吗?更好的方式是用花括号{}来表达,看例子:可以看到,这里我们匹配了所有连续5个字母的词(包括超过5个字母的词,但只匹配到第一个5个字母)。事实上,匹配重复字符的完整语法是这样的:{m,n},它会匹配前一个字符至少重复m次,最多重复n次,{m}表示匹配m次,{m,}意味着至少有m个二流。所以,当我们在5后面加一个逗号的时候,就代表它至少匹配了5次:所以这里我们匹配所有连续5个或5个以上的单词。当匹配个数最少为4个,最多为5个时,匹配结果如下:除了使用大括号匹配一定数量的字符外,还有三种相关模式:+:匹配前一个表达式一次或多次,相当于{1,}。*:匹配前面的表达式0次或多次,相当于{0,}。?:单独用于匹配前面的表达式零次或一次,相当于{0,1},如果后面跟量词*、+、?、{},则使用量词改成非贪婪模式(匹配尽可能少的字符),默认是使用贪婪模式。看一个简单的例子,这里我们匹配正则表达式/a+/ig,结果如下:和/a{1,}/ig的匹配结果一样:使用/[a-z]+/ig可以匹配任意长度的纯字母单词:4.元字符使用元字符编写更紧凑的正则表达式模式。常用元字符如下:\d:相当于[0-9],匹配任意数字。\D:相当于[^0-9]。\w:相当于[0-9a-zA-Z],匹配任意数字、大小写字母和下划线。\W:相当于:[^0-9a-zA-Z]。\s:相当于[\t\v\n\r\f],匹配任意空白字符,包括空格,水平制表符\t,垂直制表符\v,换行符\n,回车符\r,换页符\f。\S:相当于[^\t\v\n\r\f],表示非空白字符。我们来看一个简单的例子:这里我们使用\d来匹配任意数字、字母和下划线。这里匹配了七个连续的四位数字符。5.特殊字符使用特殊字符来编写更高级的模式表达式。常见的特殊字符如下:.:匹配除换行符外的任意单个字符。\:将下一个字符标记为特殊字符,或文字字符,或反向引用,或八进制转义字符。|:逻辑或运算符。[^]:取反,匹配任何不包含的字符。让我们看一个简单的例子。如果我们用/ab*/ig来匹配,结果如下:那我们要匹配*怎么办呢?你可以用\转义它:这只会匹配ab*。或者搭配也很简单。让我们看一下这个例子。匹配规则为:/ab|cd/ig,匹配结果如下:这里会匹配字符串中所有的ab和cd字符。如果要匹配sabz或者scdz怎么办?开头和结尾相同,只有中间两个字符是可选的。其实只需要在中间或部分加上括号即可:取非规则,在范围内使用。我们看例子:这里匹配所有非字母字符。6.位置匹配如果我们要匹配字符串中以特定字符结尾的单词,如何实现以特定字符开头的单词呢?正则表达式提供了按位置匹配字符的方法:\b:匹配单词边界,即单词和空格之间的位置。\B:匹配非单词边界。^:匹配开头,多行匹配时匹配行首。$:匹配结尾,多行匹配时匹配行尾。(?=p):匹配p之前的位置。(?!=p):匹配一个不在p前面的位置。最常见的是匹配开始和结束位置。先来看一个起始位置匹配,这里使用/^ex/igm来匹配多行以ex开头的行:使用/e$/igm来匹配e结尾的行:可以使用\w+$匹配每行的最后一个单词:需要注意的是,这里我们都是使用m修饰符来开启多行模式。使用/(?=the)/ig来匹配字符串中人脸之前的位置:我们可以使用\b来匹配单词的边界,匹配结果为如下:这个可能比较难理解,我们可以使用下面的正则表达式来匹配完整的单词:\b\w+\b,匹配结果如下:4.修饰符正则表达式常用的修饰符有如下:g:表示一个全局模式,适用于所有字符串。i:表示不区分大小写,即匹配时忽略字符串的大小写。m:表示多行模式,强制$和^分别匹配每个换行符。这些修饰符总是在最后一个正斜杠之后使用,并且可以一起使用。下面分别来看看这些修饰符的作用。在原来的例子中,字符串中有两个“where”,但只匹配了一个。这是因为正则表达式默认匹配第一个匹配字符。如果要匹配所有符合条件的字符,可以使用g修饰符:/at/g这样就可以匹配所有符合条件的字符:当需要匹配一个带引号的英文字符串,并且忽略字符串的字母大小写的时候,i修饰符就派上用场了。我们先看下面的表达式:当匹配到/a/g时,它匹配到字符串中的所有字符。但是第一个A没有匹配到,因为两者的大小写不一致:那我们加上i修饰符:/a/gi这时候,所有的a都匹配到了,不管是大写还是小写,一共匹配了三个a:还有一个小问题,如果正则表达式是通过对象构造函数来构造的,如何添加这些修饰符呢?其实很简单,只要将修饰符作为第二个参数传递给构造函数:letregExp=newRegExp('[2b|^2b]','gi')console.log(regExp)//输出结果:/[2b|^2b]/gi五、RegExp实例1.实例方法RegExp实例设置了test()和exec()两个方法来验证正则表达式。我们分别来看一下这两种方法。(1)test()test()用于检测一个字符串是否匹配某种模式,如果字符串中包含匹配的文本,则返回true,否则返回false。constregex1=/a/ig;constregex2=/hello/ig;conststr="行动胜于雄辩";console.log(regex1.test(str));//trueconsole.log(regex2.test(str));//false(2)exec()exec()用于检索字符串中正则表达式的匹配。该函数返回一个数组,其中存储了匹配结果。如果未找到匹配项,则返回值为null。constregex1=/a/ig;constregex2=/hello/ig;conststr="行动胜于雄辩";console.log(regex1.exec(str));//['A',index:0,input:'行动胜于雄辩',groups:undefined]console.log(regex2.exec(str));//在全局正则表达式中使用exec时每隔一段时间使用null就会返回null,如图:怎么回事?MDN解释如下:当设置全局或粘性标志(例如/foo/g或/foo/y)时,JavaScriptRegExp对象是有状态的。他们将在lastIndex属性中记录自上次成功匹配以来的位置。使用此功能,exec()可用于迭代单个字符串中的多个匹配项(包括捕获的匹配项),相比之下,String.prototype.match()将仅返回匹配的结果。为了解决这个问题,我们可以在运行每个exec命令之前为lastIndex赋值0:2。实例属性RegExp实例还有一些内置属性,可以获取正则表达式各方面的信息。但不是很有用。属性描述全局布尔值,表示是否设置g标志ignoreCase布尔值,表示是否设置i标志lastIndex整数,表示开始搜索下一个匹配的字符位置,从0开始计数多行布尔值,表示是否设置了m标志源正则表达式的字符串表示根据文字形式而不是传递给构造函数的重要字符串模式进行匹配。6.字符串方法JavaScript中常用的方法有6个,都支持正则表达式。我们分别来看这些方法。1.search()search()方法用于检索字符串中指定的子串,或者检索与正则表达式匹配的子串,返回子串的起始位置。如果未找到匹配的子字符串,则返回-1。constregex1=/a/ig;constregex2=/p/ig;constregex3=/m/ig;conststr="行动胜于雄辩";console.log(str.search(regex1));//输出结果:0console.log(str.search(regex2));//输出结果:8console.log(str.search(regex3));//输出结果:-1可以看出,search()方法只会返回第一个匹配到的字符的索引值,没有匹配到对应值时返回-1。2.match()match()方法可以检索字符串值中的指定字符,或者为一个或多个正则表达式寻找匹配项。如果找不到匹配的文本,match()将返回null。否则,它返回一个数组,其中包含有关它找到的匹配文本的信息。constregex1=/a/ig;constregex2=/a/i;constregex3=/m/ig;conststr="行动胜于雄辩";console.log(str.match(regex1));//输出结果:['A','a','a']console.log(str.match(regex2));//输出结果:['A',index:0,input:'行动胜于雄辩',groups:undefined]console.log(str.match(regex3));//输出结果:null可以看到,当没有g修饰符时,字符串中只能进行一次匹配,如果要匹配所有符合条件的值,需要加上g修饰符。3.matchAll()matchAll()方法返回一个迭代器,它包含所有匹配正则表达式和分组捕获组的结果。因为它返回一个迭代器,所以通常使用for...of循环检索它。for(constmatchof'abcabc'.matchAll(/a/g)){console.log(match)}//["a",index:0,input:"abcabc",groups:undefined]//["a",index:3,input:"abcabc",groups:undefined]需要注意的是,该方法的第一个参数是一个正则表达式对象,如果传入的参数不是正则表达式对象,则会隐式使用newRegExp(obj)将其转换为RegExp。另外,RegExp必须是设置全局模式g的形式,否则会抛出异常TypeError。4.replace()replace()用于将字符串中的某些字符串替换为其他字符串,或者替换与正则表达式匹配的子字符串。const正则表达式=/A/g;conststr="行动胜于雄辩";console.log(str.replace(regex,'a'));//输出结果:动作胜于雄辩可见,一个参数中的正则表达式匹配字符串中第一个大写的A,并将其替换为第二个参数中的小写a。5.replaceAll()replaceAll()方法用于用字符串中的其他字符替换某些字符,或者替换与正则表达式匹配的子字符串。此函数将替换所有匹配的子字符串。const正则表达式=/a/g;conststr="行动胜于雄辩";console.log(str.replaceAll(regex,'A'));//outputresult:ActionspeAkthAnwords需要注意的是,使用Aregex时,必须设置global("g")flag,否则会抛出TypeError:"replaceAllmustbecalledwithaglobalRegExp".6.split()split()方法用于将字符串拆分为字符串数组。它的第一个参数是一个字符串或正则表达式,从参数指定的地方分割字符串。constregex=//gi;conststr="行动胜于雄辩";console.log(str.split(regex));//输出结果:['Action','speak','louder','than','words']这里的regex是用来匹配一个空字符串的,所以最后把字符串拆分成一个数组在每个空格处字符串。七、实际应用下面我们通过正则表达式的几个实际应用来巩固以上知识。1、匹配密码查看密码格式,至少包含一个大写字母、小写字母、数字、符号,长度为8-12位:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*\W).{8,12}$/g这里我们主要使用正则表达式中的positivelookahead,positivelookahead的语法is(?=pattern),即在目标字符串的对应位置一定有pattern的部分匹配内容,但不会作为匹配结果处理,不会存入buffer供以后使用。让我们看看这个正则表达式的每一部分是什么意思:(?=.*[a-z]):匹配任何后跟小写字母的字符。(?=.*[A-Z]):匹配任何后跟大写字母的字符。(?=.*\d):匹配任何后跟数字的字符。(?=.*\W):匹配任何后跟符号的字符。.{8,12}:匹配的长度必须至少为8个字符,最多为12个字符。^和$可以保证从字符串的开头匹配到结尾,即只匹配整个密码,不考虑部分匹配。以下为测试结果:2、匹配邮箱查看邮箱地址:/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/g我们来看看这个正则表达式各部分的含义:^[a-zA-Z0-9.!#$%&'*+/=?^_~-]+:检查是否使用了所有有效字符,并且至少有一个(末尾的+`用于检查至少有一个字符)。[a-zA-Z0-9-]+:这部分用于检查主机名是否有效。主机名可以是大小写字母、数字和破折号。末尾的+表示至少有一位数字。(?:\.[a-zA-Z0-9-]+)*:这部分为可选域名后缀,这里的*表示前面的字符为0orMultiple,这样可以匹配.com,.com.cn等域名。^和$可以保证从字符串的开头匹配到结尾,即只匹配整个邮箱字符串,不考虑部分匹配。以下是测试结果:3.匹配数字检查数字是否为整数:/^\d+$/,其中\d+表示至少有一位。测试结果如下:检查数字是否为小数:/^\d*\.\d+$/,其中\d*表示至少有0位,\.即小数点转义,\d+表示至少有一位小数。测试结果如下:判断一个数是否为金额:/^\d+(.\d{2})?$/。八、实用工具1、Regex101Regex101是学习正则表达式最有效的工具网站之一。可以在REGULAREXPRESSION栏中输入正则表达式,在输入框右侧选择需要的修饰符,在下方的TESTSTRING栏中输入要测试的字符串,就会显示匹配结果。在右边的EXPLANATION区域,会显示对输入的正则表达式的详细解释。右下角的快速参考列显示正则表达式快速参考。Regex101也支持在上面写正则表达式:可以在上面搜索一些正则表达式库:此外,我们还可以使用RegexDebugger来跟踪匹配过程。可以在Regex101上探索更多功能。官网:https://regex101.com/。2.RegExrRegExr是一个基于JavaScript开发的用于创建、测试和学习正则表达式的在线工具。它是一个具有以下功能的开源工具:在您键入时,结果会实时更新。支持JavaScript和PHP/PCRERegEx。将匹配项或表达式移动到详细信息。保存并与他人分享表情。使用工具探索结果。浏览参考以获取帮助和示例。使用cmd-Z/Y在编辑器中撤消和重做。官网:https://regexr.com/3、RegexPalRegexpal是一款基于Javascript的在线正则表达式校验工具。它的页面非常简单,只有两个输入框。上方输入框可以输入正则表达式(匹配规则),下方输入框可以输入需要匹配的数据。另外,根据具体需求,还可以设置忽略大小写、多行匹配等参数。官网:https://www.regexpal.com/,4、Regex-VisRegex-Vis是一个辅助学习、编写和验证正则表达式的工具。它不仅可以将规律可视化,还提供了对规律进行可视化编辑的能力。输入正则表达式后,会生成它的可视化。然后可以在图中单击或选中单个或多个节点,然后在右侧的操作面板中对其进行操作。添加量词等。官网:https://regex-vis.com/。5、RegexpreviewerRegexpreviewer是一个VScode插件,在插件市场搜索名称即可安装。我们在写正则表达式的时候,可以直接使用快捷键Ctrl+Alt+M(windows)或者?+?+M(Mac)在编辑器的右侧起一个tab,我们可以用这个tab来写页面上的一个测试用例来测试我们编写的正则表达式。写好字符串用例后,点击我们写的正则表达式上方的TestRegex...,这样右边匹配到的字符就会高亮显示,如下图: