为了账号安全,请及时绑定邮箱和手机立即绑定

一起扫荡JavaScript(八)—— 正则表达式的魅力

标签:
JavaScript

    很多人第一眼看到正则,都会觉得特别难,或者读起来理解起来很费劲,直接百度不就好了?其实百度一个也许解决了问题,但你的疑惑还在,因为你不知道它为什么就可以?尽管那么多的规则记起来你会觉得是一个大坑,其实可能你缺的是一个应用场景。

    这里的话不列一堆表格出来跟你说规则,我们贴几条正则出来,一起体会一下它的魅力吧。

    贴之前我们先来理解一下“()”和"[]"这两个有什么区别,这是前提。

    “()”代表的是整段的匹配

    “[]”代表的是一个个字符的匹配

https://img1.sycdn.imooc.com//5c8cad4d0001dd3903690098.jpg

    你会发现,实际上“()”会先把里面的所有规则组成一整段的规则片段,再去字符串中找,找到的就是整段的,比如这里的abc,而“[]”里面的是一个个去找,能有一个满足就OK。

https://img1.sycdn.imooc.com//5c8cae2700014c4c03880101.jpg

    你会发现,abcde在abcd这个字符段中没有完整的,所以返回null。而下面的只要有a、b、c、d、e其中一个或多个,都会统统给你匹配出来。

    接下来先看第1个场景:

    比如说你从某个接口拿到的数据是这样:

~fc3243a9f2225d47371b4ad13cdfa81c#2018-07-12 09:53:01>19^26^79^85|2^1^1

    你可能要拿到其中的时间,传统的方式你可能是这样:

https://img1.sycdn.imooc.com//5c8ca8e20001244f09300149.jpg

    这样可以,但种种split(),看着很不优雅,而且假如后期改动了,比如">"号换了,那就坑了对吧?那用正则呢?

https://img1.sycdn.imooc.com//5c8cafb600010ab706310053.jpg

    什么意思呢?看着好拗口啊,我们慢慢来分析。上面先不管:

    我们明确一下要匹配的是时间,2018-07-12 09:53:01,实际上我们直接这样匹配也是OK的:

https://img1.sycdn.imooc.com//5c8cab110001a8f304650058.jpg

    你会发现,正则,其实就是把匹配的字符串扔进匹配目标里面(通过//,或者new RegExp()等特定的JS语法,有个g代码整段字符串都匹配),没啥。上面直接扔一串进去虽然可以,但不符合一般性原则,因为我们写的正则得通用是吧,得所有的时间都能匹配到,所以就有了一个规则:

    0-9或者\d,这两个都是匹配字符,\d代表数字。说到这。

    我们要匹配这个:2018-07-12 09:53:01

    2018都是数字,换成\d,但\d只代表一个数字啊,我这有4个呢,所以来一个{4},后面分析一样。

    你是不是就可以直接写出这样的正则了?(\s是空格符,各种转义字符了解一下即可)

/\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}/g

https://img1.sycdn.imooc.com//5c8cb1350001a8d909930446.jpg

    这样就是刚刚你觉得拗口的一串正则,这是最笨的办法,但起码能匹配出来,那有什么改进方法呢?

    我们现在知道了“()”可以一整段来匹配,{数字}可以匹配重复的某个片段对吧?

    你发现上面-07,-12,:53,:01了没?好多重复啊,假如说这种重复100次?难道要写一串100个那个的正则?当然没必要,有没有简化的办法?有。

https://img1.sycdn.imooc.com//5c8cb26b0001bc3205350059.jpg

    你说,我去这个也不直观啊,emmm,我们分析一下:

https://img1.sycdn.imooc.com//5c8cb4690001945c11960639.jpg

    这样子如果出现100个片段,只需要把{2}改成{100}就OK了。

    第2个场景:

    假如说要让你写一个函数,将一个url上的参数转化成一个对象。你会怎么做?

    还是split(""),split(""),split("")吗?

    我们先看一下传统的url大致的构成是怎样的?

http://www.baidu.com/login/autoLogin.jsp?user=dorsey&pwd=123456&hello=dhaoisha&dorsey=dhjaposjp&url=http:123.213.321.21:8088/first/second/artical.html

    那用正则怎么拿?

    首先要确认,我们到底要匹配什么?注意到参数的前面要么有“?”要么有“&”,那我们不就直接匹配?与&之间的那串字符串就好了啊。变成这样:

https://img1.sycdn.imooc.com//5c8cb7b700010e8208870148.jpg

    怎么匹配呢?首先拆开来看。

https://img1.sycdn.imooc.com//5c8cb89c000140aa09190272.jpg

    一、?或者&之后。

    二、&之前

    三、最后一个参数末尾没有&,它不需要“&之前”

    这是我们观察url得出的结论对吧?

    这个正好正则里面有:

    先行断言:?=

    后行断言:?<=

    先别管这两个很拗口的专有名词。我们一条条规则来满足。

    首先:?或者&之后

    很简单我们就想到“[?&]”,但是?在正则本身是有特殊含义的,像“/、^、$、.、*、?、()、[]”这些是有特殊含义的,那怎么匹配?呢?改成这样“[\?&]”,即加一个\转义符号就行了。

    但正则怎么知道 之后 呢?

    这就是上面的后行断言,代表的就是匹配某某片段之后的字符。

    这样就变成了:?<=[\?&]对吧?

    其次:&之前

    根据上面简单的理解就很容易得出:

    ?=&对吧?

    最后:最后一个参数末尾没有&,它不需要“&之前”

    $,代表最后,以什么结尾。

    记得与(&)或(|)非(!)吗?这几个其实很常见。

    这不就是一个或吧。

    它在&之前或者$之前,

    那上面的?=&实际上就变成了?=&|$。

    这样我们就有了。

    ?<=[\?&]    和    ?=&|$

    但是我们是要中间的字符串是吧?中间的怎么表示呢?

    首先中间可以是任意字符“.”,任意个数对吧?“*”(代表0个也可以),还得给个条件,因为你是?之后&之前,你可能直接变成了。

https://img1.sycdn.imooc.com//5c8cbce100014f4810560156.jpg

    因为匹配是贪婪的,js它可能直接拿你最后一个&,那怎么办?

    这就是?的妙用了,它代表着保守,只要最短的那条。

    这样就变成了:

    https://img1.sycdn.imooc.com//5c8cbd440001212d11140267.jpg

    是不是特别简单?

    这样你再映射成对象就好了。

https://img1.sycdn.imooc.com//5c8cbd83000191d209670396.jpg

   是不是很简单?

    好了,好好体味这个过程,相信你会有收获的。

    

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
1.3万
获赞与收藏
1519

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消