彻底理解正则表达式

一、前言

正则表达式,在平常的开发中也是司空见惯了,比如手机号、邮箱、密码等规则校验都是需要用到正则。

二、理解正则需要做的事情

可以总结为下:
1、匹配啥? 2、匹配不是啥? 3、匹配多少次

1、匹配啥

这个比较好理解,比如像匹配字符a,那就直接写/a/,只要字符串某个位置是a就可以匹配上:

/a/.test('javascript')   //true

匹配以a开头的字符串 就加上元字符^(开始位置标识),/^a/:

/^a/.test('javascript') // 不是以a开头 返回 false
/^a/.test('abc')  //以a开头 返回 true

匹配以a结尾的字符串,就加上元字符$(结束位置标识),```/a$/

/a$/.test('javascript') // 不是以a结尾返回false
/a$/.test('cba') // 以a结尾 返回 true

匹配字符a或b,可以把对应的字符放入中括号里/[ab]/,只要字符串包含a或者b就可以匹配上

/[ab]/.test('byte') // true

匹配字符串abc或者xyz ```/abc|xyz/

/abc|xyz/.test('aabbxyz') // 本字符串包含xyz 所以返回true

①匹配啥前面的(前瞻)
exp1(?exp2):匹配exp2前面的exp1,匹配结果不包含exp2
比如要匹配字符串中的script前面的部分java,/java(?=script)/

/java(?=script)/.test('javascript,javaee,typescript') // 字符串中javascript符合规则 会返回 true

// 1、用exec方法来验证下面的匹配结果
/java(?=script)/.exec('javascript,javaee,typescript')
//2、得到匹配结果如下:
["java",index:0,input:"javascript,javaee,typescript",groups:undefined]
//3、会发现匹配到的是java,index是0,说明找到了的是JavaScript中的script前面的java

②匹配啥后面的(后顾)
(?<=exp2)exp1:匹配exp2后面的exp1,匹配结果不包含exp2
比如要匹配字符串中java后面的ee,/java(?<=ee)/

/(?<=java)ee/.test("javascript,javaee,typescript") //字符串中javaee符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/(?<=java)ee/.exec("javascript,javaee,typescript") 
//2、得到匹配结果如下:
["ee", index: 15, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是ee,index是15,说明找到了的是javaee中java后面的ee
匹配不是啥?

匹配不是啥就是取反,只要不是这些的都可以匹配,比如不相匹配字符a,正则写法为/[^a]/,是在中括号中加上元字符^```,这样只要字符串满足又不是这个集合里面的字符,都可以被匹配上:

/[^a]/.test('aaa') // 字符串全是a, 返回false
/[^a]/.test('abc') // 字符串不全是a,返回true

匹配不是以a开头的跟之前匹配啥类似,加上^/^[^a]/

/^[^a]/.test('javascript') // 此字符串不是以a开头 返回 true
/^[^a]/.test('abc') // 此字符串是以a开头 返回false

匹配不是以a结束的,也跟之前匹配啥类似,加上元字符$/[^a]$/

/[^a]$/.test('javascript')  // 此字符串不是以a结束 返回true
/^[^a]/.test('cba')  // 此字符串以a结束 返回false 

不匹配字符串a、b、c可以把对应的字符串都放入到中括号中/[^abc]/

/[^abc]$/.test('abccba') // 此字符串全部都不符合 返回 false

① 匹配后面不是啥的(负前瞻)
exp1(?!exp2):匹配后面不是exp2的exp1,匹配结果不包含exp2
比如要匹配字符串中后面不是script的java, /java(?!script)/

/java(?!script)/.test("javascript,javaee,typescript") //字符串javaee符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/java(?!script)/.exec("javascript,javaee,typescript")
//2、得到匹配结果如下:
["java", index: 11, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是java,index是11,说明找到了的是javaee中的java,因为这个java后面是ee

② 匹配前面不是啥的(负后顾)
(?<!exp2)exp1:匹配前面不是exp2的exp1,匹配结果不包含exp2
比如要匹配字符串中前面不是java的script,/(?<!java)script/

/(?<!java)script/.test("javascript,javaee,typescript") //字符串中typescript符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/(?<!java)script/.exec("javascript,javaee,typescript")
//2、得到匹配结果如下:
["script", index: 22, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是script,index是22,说明找到了的是typescript中type后面的script

③ 不匹配包含abc的字符串
这是一个比较特殊的匹配行为,如果只是写成/[^abc]/的话,这只意味着字符串不能全是由a、b、c这三个组成的,跟需求不匹配。
那我们要从另外一个角度去分析,字符串的任意一个位置开始都不能连续出现abc,我们可以利用负前瞻的特性来匹配,然后一步一步来实现这个正则:
1、位置后面不能是abc,使用负前瞻匹配位置:/(?!abc)/
2、从开始到结束每个位置都要覆盖到,添加开始结束标记:/^(?!abc)/$
3、这个位置后面可以是其他的字符,用\w来表示:/^(?!abc)\w$/
4、满足上面情况后的位置,可以连续出现多个,用+来表示数量:/^((?!abc)\w)+$/

/^((?!abc)\w)+$/.test("cbacbac") //本字符串中不包含连续的abc,结果返回true
/^((?!abc)\w)+$/.test("cbacbabc") //本字符串中包含连续的abc,结果返回false
3、匹配多少次?

匹配一次可以什么都不用定义,比如匹配一个数字/\d/,如果要匹配连续是三个数组最简单的方式就是连续写三次:/\d\d\d,这样写本身没有问题,能正确匹配。
但是如果次数太多 或者次数不确定,肯定就有问题了,所以可以加上长度规则
*:匹配任意次
+:最低匹配一次
?:匹配1次或者0次
{m}:匹配m次
{m,}:最低匹配m次
{m,n}:最低匹配m次,最多匹配n次,m需要小于等于n
正则默认是贪婪匹配,就是符合条件的会一直匹配,如果想阻止贪婪匹配,可以在长度规则后面加上一个?,比如

/\d{2,}/.exec('1234567890')
//得到匹配结果如下:会匹配到所有的数字:
["1234567890", index: 0, input: "1234567890", groups: undefined]

// 1、添加?,会阻止非贪婪匹配后
/\d{2,}?/.exec('1234567890')
//2、得到匹配结果如下,只会匹配2个数字:
["12", index: 0, input: "1234567890", groups: undefined]

① 使用分组
如果想匹配多次某个单词如regregregregregreg时候怎么办,我们看到reg连续出现了6次,如果傻傻的把6个reg写在了正则表达式中肯定不合适,我们就可以利用分组来实现,我们把reg放在括号里面,然后让这个分组重复6次,/(reg){6}/

/(reg){6}/.test("regregregregregreg") //匹配成功,返回true

不过这样利用分组是有个前提,就是知道要匹配的字符串就是reg,然后重复这个分组。如果想匹配类似8899或者5522这种重叠类型的字符怎么办呢?那我们可以把重叠的第一个放入分组,再通过\n捕获这个分组内容来匹配下一个:

/(\d)\1(\d)\2/.exec("2345566789")
//得到匹配结果如下,返回了5566,分组对应的5、6也被返回
["5566", "5", "6", index: 3, input: "2345566789", groups: undefined]

② 分组捕获
默认的分组是可以被捕获的,上面的\1\2是在正则表达式内部捕获的分组。如果想在外部去捕获分组匹配的数据可以使用RegExp.$1-$9来获取。只要正则匹配了就会有。可以使用testexec或者str的replace方法来获取$1-$9

使用test:

/([a-z]{2})(\d{2})/.test("xyz123")
RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
RegExp.$2 //返回第二个分组表达式匹配到的内容 12

使用replace:

"xyz123".replace(/([a-z]{2})(\d{2})/,'$2$1')
//会返回结果:x12yz3,就是把第一个分组匹配到的内容yz和第二个分组匹配到的内容12互换了

③ 分组不捕获
如果不想捕获分组,只需要在分组内加上?:就可以了

/([a-z]{2})(?:\d{2})/.test("xyz123")
RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
RegExp.$2 //分组未被捕获 返回空字符串

转自:https://juejin.cn/post/6939854031787393031

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 1、前言 正则表达式,如果有一定编程经验的同学,一定知道,可能你知道,但又说不出个所以然来,平时不经常使用,很容易...
    iHTCboy阅读 645评论 0 0
  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,896评论 0 20
  • 带你入门(几个小小点) 目录 正则表达式的使用 正则表达式的基本构成元素 正则中的类(分类),基本的元字符 + 五...
    南航阅读 654评论 0 2
  • 正则表达式——基本语法 正则表达式(Regular Expression)是计算机科学的一个概念。正则表达式使用单...
    南山码农阅读 387评论 0 1
  • 正则表达式(Regular Expression)是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系...
    草鞋弟阅读 724评论 0 0