正则表达式-茫茫人海龥(遇)见你

673 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

正则表达式是啥

说实话,正则表达式这东西,不应该算作前端的内容,在各种编程语言里面都会用到。尤其是在数据分析大热的今天,爬虫中少不了正则表达式的影子。

说到这个就让我想起了前天晚上爬了一宿爬了十万个多个网页就59个命中结果的惨剧:

那么,首先还是先摆一下概念,什么是正则表达式呢?简单来说,就是按照文本的特点来查找文本,就跟找对象一样,你可能想找个丑的,隔壁家二狗子和杭州的马爸爸就命中了;我想找个大波浪的,结果柳岩就命中了(对,这是两个特点)。如果你想要找所有的数字,输个表达式[0-9](这里只代表找一位数),于是数字们就命中了(两边的斜杠表示的是表达式的开始和结尾,那个g表示的是全局匹配,而不是第一个就停):

(这个正则表达式的测试工具地址:regexr.com/

具体用法先上一张图,然后我开始讲故事:

image.png

一个大龄青年的相亲之路

赚的够多

钱,估计是最让人关注的话题了,毕竟那么多基本条件都是以钱为基础的。于是大龄青年向潜在对象们询问了年薪有没有六位数:

/[0-9][0-9][0-9][0-9][0-9][0-9]/

于是得到了这样的回应:

嗯,对,我胜出了,打败了马云爸爸……大龄青年发现自己表达错了,她说的应该是“有谁是年薪6位数以上的”:

/[0-9][0-9][0-9][0-9][0-9][0-9]+/

加上了个加号就代表把最后那个[0-9]需要出现一次或者无数次。

同样道理加入*代表零次或者无数次:

/[0-9][0-9][0-9][0-9][0-9][0-9]*/

这样隔壁二狗就可以入选了。

或者加上?(注意是英文符号),代表前面那个[0-9]只出现零次或者一次

/[0-9][0-9][0-9][0-9][0-9][0-9]?/

马云爸爸这样就又被排除在外了,因为太有钱……

历尽千辛万苦留住了我和马云爸爸,可是大龄青年又在想,这是问年薪啊,万一问道存款不得说一堆[0-9]吗?这样会不会因为话唠给对方留下不好的印象啊┑( ̄Д  ̄)┍,于是想到了这么说:

/[0-9]{6,}/

左边代表最小位数,右边代表最大位数,那边不填就代表哪边是无数次

这样不就是六位数以上了吗?而且还想少说话的话,\d就代表[0-9]所有的数字啊:

/\d{6,}/

哦,终于找到赚的多的了,那下一步该问什么呢?大龄青年陷入了深思,明天先问问算命先生什么样的名字跟她更配吧,听说明天还有新的应征者呢……

名字得合

大龄青年通过年薪筛选了应征者,接下来,该去找算命先生了,先生告诉他了几个关于名字的问题:

  1. 英文名字风水不和(精通多国语言的大师啊……)
  2. 名字里带叠字的容易犯冲
  3. 带了“金”字或者带“玉”字都是八卦向合的名字(大师你不懂日语吗……)

好了,那么接下来就是开始筛选名字了,首先不能是英文名字,不如这样:

/[^\w]+/

^代表排除方括号里面字符之外的所有字符,\w代表所有的大小写字母和下划线(+号不记得意思的请到前文复习!),或者你也可以直观的这么写:

/[^a-zA-Z_]+/

这样以来,所有的带字母的都消失了,可是好像出了问题:

这名字里带空格的国际有人还是被选上了啊,而且那个叫彭一土的是什么情况啊,名字里带那么多乱七八糟的东西?能不能只选择中文呢:

/[一-龥]/

这个表达式就表示几乎所有的汉字了,为什么呢,因为每个国家的字符在计算机中均有一套编码(unicode码)来规定的,这个编码是16进制的,而所有的汉字的编码就都在一和龥(这个字念“龥”,对茫茫人海龥见你,就是这标题),所以这个表达式就足够表达了所有的汉字了。龥字打不出来?那就可以这么写:

/\u4e00-\u9fa5/

\u后面跟上三个十六进制数字就代表一个字符,而一的字符就是4e00,而龥则是9fa5:

(⊙o⊙)哦这样的话国际友人就拜拜了(关于那个名字乱七八糟的家伙下面解决,之后讲边界匹配),接下来帮大龄青年解决下一个问题,名字里不能带叠字。为了简单一些,这次我们先换个思路,我们直接来筛选出名字里带叠字的人(其实你也可以使用^符号来排除他们),于是要这样做:

/([一-龥])\1/

我们先看效果:

为什么被选择出来了呢,主要归功于两个符号第一个是(),第二个是\n(n代表一个数字)。这里()中的表达式被暂时保存了下来,按照顺序排列,你可以使用\1 \2 \3来重新使用它们,比如找出这个非主流的名字:

啊,大龄青年感叹,真是世界之大无奇不有啊,非主流的也要淘汰……

最后,就是要筛选金玉了(日语达人不要看这里!)

/[一-龥]+金|玉/

|表示左右两边的字符任选其一出现即可,那么结果就是:

哇,终于选到了合适的名字,大龄青年终于看到了脱单的希望!

吹毛求疵

前面说道,经过多轮的筛选之后,大龄青年终于选出了几个候选人,于是,便开始了吹毛求疵之路(我说了肯定是因为这样才成了大龄青年的)。。。。

首先,大龄青年要追求“见不到的东西”,首先,她还是想嫁给歪果仁啊,于是找找名字里带空格的吧:

/\S+\s\S+/

其中\S代表任意非空白字符,\s代表任意空白字符,+号还记的什么意思吧,代表前面的表达式要至少出现一次。

嗯……那个Jack指不定是个假老外……

对了,说起任意空白字符,它们有个学名叫非打印字符,给它们来个全家福吧:

接下来,大龄女青年要求所有人给出自己的座右铭。

难道这是个文艺女青年吗?不……她并不是想看座右铭,她只是想筛掉那些不记得写句号的人……可是,如果直接写个

/。/

中间带句号的也被选出来了啊,不行不行。这时候就要用到边界匹配了:

/。$/

加上一个$,表示到这里就到了边界,于是:

同样道理,如果前面加上^,也代表前面的边界:

/^雪/

最后,大龄女青年又提出了一个要求,要看各位的微信帐号,要求是“必须以数字结尾”,而且这次的数据还很奇怪,都写在一行里了,用^和$没法筛选了,于是只能求助于\b了:

/\d\b/

还记得吧,\d代表着所有的数字,而这里的\b就是指的字符边界了,你可以理解它为单词结尾的空格(当然写在前面就是单词前面的边界有时候就不是空格啦):

同样道理,用大写的B就是跟它唱反调了,就是非字符边界了:

/\d\B/

这里就选中了不以数字结尾的词。

啊,相亲进行到这里,大龄青年终于累了,最后,她做了个艰难决定:

是个人都行!

于是……她最后使用了通配符.

/./

"."代表了除换行符\n外的所有字符,所以终于……有情人终成眷属了!恭喜恭喜!

最后记得再看下我做的思维导图巩固一下哦:

image.png