引子
我在学习JavaScript时遇到下面这个题目:
编写一个函数validateEmail(str),要求该函数能判断字符串参数str是否符合Email的格式,符合返回true,否则返回false。Email格式的判断条件:包含@和.字符;@字符在.字符的前面;@不是第一个字符;.不是最后一个字符;@和.之间还有其它字符。
我当时的想法是嵌套各种if和循环,但觉得非常麻烦且复杂,于是我决定去网上找找有没有优雅简洁的解决方案,结果发现了使用正则表达式可以做到。
什么是正则表达式?
- 就是用如下特殊符号或其组合来代表某个字符(以下符号可以通配所有字符)
符号 说明
. 代表除换行符以外的任意字符
\w 代表字母或数字或下划线或汉字
\s 代表任意的空白符
\d 代表数字
\b 代表单词的开始或结束
^ 代表字符串的开始
$ 代表字符串的结束
如 abc120 可以用这样的正则表达式表示: \w\w\w\d\d\d, 或者 \w\w\w\w\w\w 或者 …… (六个英文句点) 等等…
- 用如下符号来代表某个可能字符的集合
[ ]
如电话号码的第n位,一定属于这个集合 [0-9] ,即0到9;某个外国人名字的第n个字母,一定属于这个集合 [a-z A-Z],即26个英文字母的大小写组成的集合
- 用如下符号来代表 上面所表达的某个字符或某个集合的重复:
符号 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
- 然后剩下的符号基本就是原意了,如 邮箱符号 @ 就表示邮箱符号,等号 = 就表示等号, 横杠 – 就表示横杠等
举个例子吧,给你解释一下下面这个判断邮箱格式的正则表达式的意思(下面看不懂的可以查看上面给的各个符号的意义):
^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+$
把上面的表达式分段,并介绍每个字段的意思
1 ^ ;
2 [a-zA-Z0-9_-]+ ;
3 @ ;
4 [a-zA-Z0-9_-]+ ;
5 \\. ;
6 [a-zA-Z0-9_-]+ ;
7 $
- ^ 代表一切判断从此处开始 (段1)
- [a-zA-Z0-9_-] 方括号表示集合 这个方括内的意思是告诉执行程序的那货(其实就是电脑):嘿,编译器老兄,你帮我看看这个邮箱地址的第一个字符,只要它属于集合[a,z],或者集合[A,Z],或者集合[0,9],或者集合{“_” , “-“}的话,你就随时待命,准备执行我下一步的任务;否则,你就可以先下班,别鸟这个邮箱地址了,它的格式肯定是错的
- +加号表示重复一次或多次 加号的意思是告诉电脑:嘿,编译器老兄,你顺便帮我看看这个邮箱地址的第二个字符、第三个字符、第四个字符……看看这些字符是不是都属于同上一条的那些集合(即重复)。如果符合,你就再顺便帮我判断第五个字符是不是也属于上条那些集合呗…嘿嘿 (段2)
- 编译器这时候就疑惑且不高兴了,它反问我一句:尼玛,难道让我一个字符一个字符的一直判断下去?!我多会才能停呀…
- 这时候我告诉编译器,嗯,记住,当你看到一个字符长得像这个样子的时候,你就可以先停一停了…
- “@” 艾特符 (段3)
- 编译器很高兴,于是它就根据给定的邮箱地址,开始一个字符一个字符地判断起来,直到它顺利地看见了”@”(艾特符),这时编译器喜上眉梢,只见他长出一口气,刚准备说:我先歇一会…
- 这时我告诉编译器:不行不行,工作还没完成呢,你继续帮我判断跟在”@”符号后的那些字符,看看他们是不是属于第一条的那些集合(段4)…
- 编译器撅着嘴继续判断起来,然后他一边判断一边又问:那我多会才停下来呢?
- 我告诉编译器,当你看见这个字符的时候就先停下来
- “.” 英文句号 (段5)
- 编译器于是继续判断着,奇了怪了这邮箱地址格式一路正确,于是它走到了英文句号跟前(“.”)停下了,看上去有点想罢工的样子了
- 于是我赶紧说道,老兄,最后一件工作了,真的最后一件了!把跟在英文句号(“.”)之后的那些字符也依次判断一下吧,只要他们仍属于第一条所列的那些集合,你就可以停下了 (段6)
- 编译器此时面露喜色,跟着开始判断起英文句号(“.”)之后的那些字符来,但是他突然脸一黑,想到:尼玛,要是这个字符有100多个,1000多个,难道我就一直这么判断下去,我不走火入魔了才怪呢!于是他对我说:要是有1000多个字符,难道就让我一个一个判断下去,我根本下不了班了呀!
- 我说:老兄,不用着急。首先,你不会遇到这么长的字符,其次,记住,只要你看见下面这个字符,就可以彻底下班走人了。
- 这个字符就是:”$” 刀勒符,它的意思就是告诉编译器,判断条件已经到结尾,一切判断到此为止 (段7)
然后这道题的答案就是:
/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/
让正则表达式可视化
然而看完了这些,你可能还是会感到很枯燥,直到今天早上我在V2EX看到大神们的评论才发现原来有两个网站可以让你更直观地认识正则表达式。


这两个网站就是regexper.com和regex101.com
打开你会发现全都是英文,别怕,其实很容易上手,下面就来给大家介绍。
首先打开regexper.com

如图,比如说输入上面题目的答案:
/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/
你就可以直观地看到正则表达式每一部分是怎样运作的。
你可能会发现开头的简短介绍没有提到「{2,3}」、「{1,2}」是什么意思,而在下图你就很清楚的看到「{1,2}」指的是重复最少一次,最多两次。

在你了解它的运行原理之后,你可能需要测试一下你的正则表达式是否真的符合需求,下面可以登录另外一个网站:regex101.com
使用起来很简单,你只需要在Regular Expression处粘贴你的正则表达式,然后然后在Test String处填入你要测试的数据,就可以了,如果匹配的话,数据的每一部分会有相应的颜色标注,就像下面这样:

如果数据不符合要求则不会显示相应的颜色,像下面这样:

对了,默认是一次只能输入一组数据,如果你想一次检测多行数据,你可以点击旁边的小旗:

在弹出的菜单中勾选「global」和「multi line」即可。

此外,在页面的右边,你还可以看到详细的解释,如果你英语水平足够好,你可以可以看看。

总结
学会找到好的资源真的很重要,一个合理的方法真的能让你节省很多学习时间。
如果你想更详细的地了解正则表达式,欢迎看看这篇文章:
最后附上完整的答案
<script>
function validateEmail(str) {
var email = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
if (email.test(str)) {
return true;
} else {
return false;
}
}
document.write(validateEmail("abc@example.com"));
</script>
这是我第一次写这么长的博客,希望大家多多指教😄,欢迎在下面留言,每条留言我都会看。
如果你对这道题有更好的解答,也欢迎在下面留言。


10 条评论关于 “让正则表达式可视化”
应该有专门讲正则表达式的教程网站吧
应该有专门讲正则表达式的教程网站吧
教程是有,但是大都枯燥无味,估计没多少人能看下去,所以本文的重点是如何让原本枯燥的东西生动起来
很赞!
谢谢!
嗯
写的很好!
谢谢!
好!
👌