携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情
正则表达式是啥
说实话,正则表达式这东西,不应该算作前端的内容,在各种编程语言里面都会用到。尤其是在数据分析大热的今天,爬虫中少不了正则表达式的影子。
说到这个就让我想起了前天晚上爬了一宿爬了十万个多个网页就59个命中结果的惨剧:
那么,首先还是先摆一下概念,什么是正则表达式呢?简单来说,就是按照文本的特点来查找文本,就跟找对象一样,你可能想找个丑的,隔壁家二狗子和杭州的马爸爸就命中了;我想找个大波浪的,结果柳岩就命中了(对,这是两个特点)。如果你想要找所有的数字,输个表达式[0-9](这里只代表找一位数),于是数字们就命中了(两边的斜杠表示的是表达式的开始和结尾,那个g表示的是全局匹配,而不是第一个就停):
(这个正则表达式的测试工具地址:regexr.com/)
具体用法先上一张图,然后我开始讲故事:
一个大龄青年的相亲之路
赚的够多
钱,估计是最让人关注的话题了,毕竟那么多基本条件都是以钱为基础的。于是大龄青年向潜在对象们询问了年薪有没有六位数:
/[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,}/
哦,终于找到赚的多的了,那下一步该问什么呢?大龄青年陷入了深思,明天先问问算命先生什么样的名字跟她更配吧,听说明天还有新的应征者呢……
名字得合
大龄青年通过年薪筛选了应征者,接下来,该去找算命先生了,先生告诉他了几个关于名字的问题:
- 英文名字风水不和(精通多国语言的大师啊……)
- 名字里带叠字的容易犯冲
- 带了“金”字或者带“玉”字都是八卦向合的名字(大师你不懂日语吗……)
好了,那么接下来就是开始筛选名字了,首先不能是英文名字,不如这样:
/[^\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外的所有字符,所以终于……有情人终成眷属了!恭喜恭喜!
最后记得再看下我做的思维导图巩固一下哦: