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

说说快速通关的常用规则

时间:2023-03-21 10:25:50 科技观察

本文转载自微信公众号《我们医大前端技术》,作者焦传凯。转载本文请联系微一大学前端技术公众号。首先推荐两个测试正则表达式的网站:https://regex101.com/https://jex.im/regulex/正则表达式大家都很熟悉了。说白了就是一堆约定俗成的匹配规则,包括模式和可能的selected修饰符。创建正则表达式对象有两种语法。更长的语法:regexp=newRegExp("pattern","flags");更短的语法,使用斜杠“/”:regexp=/pattern/;//无修饰符regexp=/pattern/gmi;//斜线“/”连同修饰符g、m和i(稍后描述)告诉JavaScript我们正在创建一个正则表达式。它就像字符串的引号。newRegExp可以动态传入参数创建正则表达式。这篇文章的主要目的是为了方便快速查找和了解需要的正则规则。修饰符i代表不区分大小写g匹配所有u根据Unicode属性匹配,使用\p{...}/u,详细属性见letregexp=/\p{sc=Han}/gu;//用来匹配中文letstr=`HelloПриветHello123_456`;alert(str.match(regexp));//你,好m多行模式,每行匹配一次(^每行匹配开头$同理)letstr=`1stplace:Winnie2ndplace:Piglet33rdplace:Eeyore`;alert(str.match(/^\d+/gm));//1,2,33字符类常用字符类:\d数??\s空格空格\w单个字符word,字母数字下划线可以组合,例如:letstr="testES6AA"letreg=/e\w\s\d/istr.match(reg)//["ES6",index:6,input:"testES6AA",groups:undefined]每个字符类都有一个反向类,代表非xx\D非数字\S非空格\W非单个字符letstr="+7(903)-123-45-67";alert(str.replace(/\D/g,""));//79031234567.匹配任意字符(换行符除外)"/ES./"\b查找目标"单词"是否在边界上,如/\bjava\b/可以匹配!爪哇!但不能匹配javacanchor^$^xx表示以xx开头xx$表示以xx结尾两者结合可以用来完全匹配consttime="12:02"letreg=/^\d\d:\d\d$///.test可以测试是否匹配reg.test(time)//true空字符串'',可以使用/^$/来匹配需要转义的字符[\^$.|?*+()setandrange[...][abc]表示'a'、'b'、'c'中的任何一个,即[a-z],[1-5]表示范围,[0-9A-F]表示0-9或A-F,[\w-]表示字母或连字符-[^abcd]表示匹配a、b、c、d以外的字符,这表示法用于排除或|a|b等同于[ab],我们可以这样使用它:gr(a|e)y严格等同于gr[ae]ygra|ey匹配“gra”或“ey””。量词控制*+?*匹配0~∞数/\d*/任意数+匹配1~∞数?匹配0或1个数字,相当于{0,1}{n}匹配n个数字,\d{3}匹配三个连续的数字,相当于\d\d\d{2,5}匹配2-5个数字{3,}matches>=3digitsgreedymodeandlazymode看例子letstr=`"hi"someword"ok"aa`letreg=/".+"/gstr.match(reg)//["hi"someword"ok"]我们其实是想匹配["hi","ok"],但是却匹配了整个句子。这是因为贪心搜索会先匹配".+匹配"时,匹配第一个引号。此时,匹配字符串为"匹配.时,匹配字符串为"h。匹配+时,字符串变成"hi"someword"ok"aa!因为后面的所有字符都符合.+的规则,即此时匹配任何不包含换行符的字符,发现匹配的太多,找不到",于是开始回溯,知道回溯变成了“hi”someword“ok”这就是贪心模式。再看一个例子:letstr=`123456`letreg1=/\d+\d+?/letreg2=/\d+\d+/str.match(reg1)//1234str.match(reg2)//123456是加在量词后面的?,那是,?+???等,会变成惰性模式,他不会一次匹配完全,而是在匹配到第一个符合条件的位时停止匹配。捕获组(...)组例如:letstr="gogogoaa"letreg=/(go)+/str.match(reg)//gogogo很好理解,就是把多个字符作为一个整体来统计匹配和connection下面看几个域名匹配的例子/([\w-]+\.)+\w+/g可以匹配格式aaa.aaa.aaaa-aa.aaa.aaemail/[-.\w]+@([\w-]+\.)+[\w-]+/g(xx)称为组(group)的概念,括号内的内容不仅在匹配时被视为一个整体,而且组中的匹配对象将返回:letstr='

Hello,world!

';lettag=str.match(/<(.*?)>/);alert(tag[0]);//

alert(tag[1]);//h1嵌套组返回的结果数组,位置[0]为普通全匹配返回值,位置[1]为值匹配在括号内。我们可以使用这种方法来制作嵌套组:letstr=``letarr=str.match(/<((\w+)\s(\w+))>/)console.log(arr[0])//console.log(arr[1])//group1group2console.log(arr[2])//group1console.log(arr[3])//group2letmatch='ac'.match(/a(z)?(c)?/)alert(match.length);//3alert(match[0]);//ac(精确匹配)alert(match[1]);//未定义,因为(z)?didnotmatchItemalert(match[2]);//cmatchAllwithg修饰符以上是没有g标签时匹配的单个对象返回的数组,所以如果有g返回多个对象,可以使用matchAll匹配:letstr=``letarr=Array.from(str.matchAll(/<(group\d)>/g))arr[0][0]//arr[0][1]//group1arr[1][0]//arr[1][1]//group2注意matchAll返回的不是数组,而是一个可迭代对象。命名组?稍微修改上面的例子letstr=``letarr=str.match(/<(?(?\w+)\s(?\w+))>/)letgroups=arr.groupsconsole.log(arr[0])//console.log(groups.g0)//group1group2console.log(groups.g1)//group1console.log(groups.g2)//group2我们可以通过添加?紧跟在括号之后,通过返回数组的groups属性得到一个group对象来代替capturegroup方法。str.replace(regexp,replacement)用替换捕获组替换str中所有匹配的正则表达式。这是使用$n完成的,其中n是组号。例如,letstr="JohnBull";letregexp=/(\w+)(\w+)/;alert(str.replace(regexp,'$2,$1'));//Bull,John为命名括号引用$。例如,让我们将日期格式从“年-月-日”更改为“日.月.年”:letregexp=/(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/g;letstr="2019-10-30,2020-01-01";alert(str.replace(regexp,'$.$.$'));//30.10.2019,01.01.2020Backreferences我们需要找到带引号的字符串:单引号'...'或双引号"..."–应该匹配两种变体。然后我们有一句话“She'stheone!”这时候如果我们使用/['"](.*?)['"]/g,它会匹配到"She',这显然是错误的。问题是,我们如何让正则表达式记住抓取的内容在我们的一个组中。此时,我们可以使用反向引用letstr=`Hesaid:"She'stheone!".`;letregexp=/(['"])(.*?)\1/g;alert(str.match(regexp));//"She'stheone!"这里的\1会找到第一组,也就是(['"])匹配的内容,也就是",那么这个正则表达式就是相当于/(['"])(.*?)"/g我们也可以用\k来引用:letstr=`Hesaid:"She'stheone!".`;letregexp=/(?['"])(.*?)\k/g;alert(str.match(regexp));//"She'stheone!"当它是y时,匹配letstr="1turkeycosts30";alert(str.match(/\d+(?=)/));//30(正确跳过单个数字1)x(?!y)仅当x后面没有跟着y时才匹配lookbehind断言(?<=y)x,matchesx,onlyify之前。(?