前言
平时的工作中有很多地方都要用到正则表达式,不得不说,正则的表达式非常强大,比如,我们常用的jquery选择器,非常方便,jquery的源码中,选择器部分应用了大量的正则表达式。然而很多时候,当我们要用到正则的时候,很多人(也包括我 == ) 的做法都是打开百度,复制粘贴,试一下,没问题,大功告成。然而,当遇到特殊需求的时候,复制粘贴大法就不好用了,所以掌握这正则还是很有必要的。下面我就结合我的一些认识对正则进行简单的介绍,如有纰漏欢迎指出。
开胃小菜
假如有这样一道题目:
请写一个邮箱验证的正则。
如果你能写出:
/@/
试一下:
var reg = /@/;
reg.test("xxx001@pingan.com.cn");//true
图示:
没毛病!
恭喜你,你已经会写正则了~ (滑稽脸)
其实这是阿里的一道技术面试题,可以写的很简单,也可以写的很复杂,至于写出来的是什么样,就要看个人功力了。
继续往下走。说到邮箱格式,我们简单分析下:
邮箱的命名方式一般分为三部分
邮件地址
@
邮箱域名地址
邮件地址部分的规则如下:
英文字母
数字
下划线
中划线
点
举几个栗子:
123456@xxx.xxx
blue.sky@xxx.xxx
123bird@xxx.xxx
ex-xxx001@xxx.xxx
根据以上规则,我们先写一下邮件地址部分:
var reg = /^\w+([-+_.]\w+)*$/;
reg.test("123456"); //true
reg.test("blue.sky"); //true
reg.test("123bird"); //true
reg.test("ex-xxx001"); //true
图示:
没什么问题, 继续往下走。
@ 直接用@匹配就可以了
域名地址部分的规则:
英文字母
数字
中划线
点
@后面的第一个字符不能是中华线和点,简单写一下:
var reg= /^@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
var reg = /^@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
reg.test("@123-abc.com.cn"); // true
最终的正则可以是这样子的:
var reg = /^\w+([-+_.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
reg.test("scau_kk@xxx.com.cn"); //true
图示:
到这里,一种简单的邮箱正则就写好了(zz,罗里吧嗦一大堆)。
后面就简单的总结下。
正式入门
字符类
首先介绍下最常见的,也是最基本的 -字符类 。
代码 | 说明 | 其它介绍 | |
---|---|---|---|
. | 匹配除了换行符之外的任何单个字符 | 举个例子,在一条句子中, 'nay, an apple is on the tree', .n 可以匹配an , on ,但是不能匹配nay ;要注意的是:一个未被转义的 . 会匹配除行结束符意以外的任何字符。 |
|
^ | 匹配字符串的开始 | ||
$ | 匹配字符串的结束 | 等同于[0-9]; 一个未转义的$ 匹配文本的结束。当指定了m标示时,它也能匹配行结束符。 |
|
\ | 转义字符 | 可以使用 来取消某些字符本身的意义,比如要想匹配. ,* 可以使用 转义字符。 另外,\1 是指向分组1所捕获的文本的一个引用,所以它能被再次匹配。 |
|
\b | 匹配单词边界 | 字符边界是一个位置,它的前后都没有其他字符,不过匹配的单词边界并不包含在匹配中。换句话说,匹配字边界的长度为零。 | |
\s | 匹配单个空白字符 | 包括空格、制表符、换行符、换行符。 | |
\S | \s 的反义,匹配空白以外的单个字符。 | 、 | |
\w | 匹配任何字母数字字符包括下划线。 | 等同于[A-Za-z0-9_] | |
\W | 匹配任何非字符。 | 等同于[^A-Za-z0-9_] | |
\d | 匹配数字字符 | 等同于[0-9] | |
\D | 匹配非数字字符 | 等同于[^0-9] |
对照着这个表格,上面的邮箱正则就很容易看了。
举几个简单的例子
console.log(/^\w+$/.test("abc")); //true
console.log(/^\d+$/.test("12345")); //true
console.log(/^\D+$/.test(" ")); //true
标示
代码 | 含义 | 用法 |
---|---|---|
g | global, 全局的 | 如果标示 g 被使用,值为true |
i | ignore, 大小写不敏感 | 如果标示 i 被使用,值为true |
m | multiLine, 多行查找( ^ 和 $ 能匹配行结束符 ) |
如果标示 m 被使用,值为true |
正则表达式量词
一般用来指定数量,常用的如下所示:
代码 | 说明 | |
---|---|---|
重复零次或更多次 | ||
+ | 重复1次或更多次 | |
? | 重复0次或更多次 | |
{n} | 重复n次 | |
{n,} | 重复大于等于n次 | |
{n,m} | 重复n到m次 |
举几个简单的例子
console.log(/^\w{3}$/.test("abc")); //true
console.log(/^\d{1,5}$/.test("12345")); //true
分支条件
正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配。
具体方法是用|把不同的规则分隔开。
我们来看看个具体的例子:
var reg = /0\d{2}-\d{8}|0\d{3}-\d{7}/;
这个表达式能匹配两种以连字号分隔的电话号码:
一种是3位区号,8位本地号(如010-12345678),
一种是4位区号,7位本地号(0755-1234567)。
或者写一个简单的匹配手机号码的正则:
var reg = /^1(3|4|5|7|8)[0-9]\d{8}$/;
分组
我们已经知道了如何重复单个字符,但如果想要重复多个字符又该怎么办呢?
这时候就可以使用分组了。
分组的类型有四种:
代码 | 用法 | 介绍 | |
---|---|---|---|
捕获型 | () | 一个捕获刑分组是一个被包围在圆括号里的正则表达式分支,任何匹配这个分组的字符都会被捕获。每个捕获型分组都被指定了一个数字。在正则表达式中第一个捕获的( 是分组1,第二个捕获( 的是是分组2。 |
|
非捕获型 | (?:前缀) | 非捕获型分组仅做简单的匹配,并不会捕获匹配的文本。 | |
向前正向匹配 | (?=前缀) | 向前正向匹配类似于非捕获型分组,但在这个组匹配之后,文本会倒回到它开始的地方,实际上并不匹配任何东西。 | |
向前负向匹配 | (?!前缀) | 向前负向匹配类似于向前正向匹配分组,但只有当它匹配失败的时候才继续向前进行匹配。 |
举个简单的例子:
实现一个验证ip地址的正则:
var reg = /^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/;
reg.test("127.0.0.1"); // true
reg.test("255.255.888.888"); // false
结合图示:
集合图示就很清晰了。
上面的部分只是正则表达式很小的一部分,篇幅有限,下一篇再做介绍。
那根据上面出现的内容,我们看一个更复杂的例子来巩固,摘自精粹,一起来看下。
一个复杂的例子
var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
var result = parse_url.exec(url);
names.forEach(function(item, index){
console.log(item + ": " + result[index]);
});
console.log(result);
// url: http://www.ora.com:80/goodparts?q#fragement
// scheme: http
// slash: //
// host: www.ora.com
// port: 80
// path: goodparts
// query: q
// hash: fragement
是不是感觉萌萌哒(滑稽脸.jpg)
看看图:
我们来分解下parse_url,看它到底是怎么工作的。
首先是 ^
, 表示字符串的开始。它是一个锚,指引exec不要跳过那些不像url的前缀,只匹配那些从开头就像url一样的字符串。
scheme
var reg = (?:([A-Za-z]+):)
这个因子匹配一个协议名,当且仅当后面跟随一个:
的时候才匹配。
(?...)
表示一个非捕获型分组。
后缀?
表示这个分组是可选的。
第一个捕获型分组的编号是1,所以该匹配的结果会出现在result[1]中。
slash
var reg = (\/{0,3});
下一个因子是捕获刑分组2,这里需要对 / 进行转义,这样就不会被解释为结束符。{0,3}
表示 斜杠 / 会被匹配 0次 或者1~3次。
host
var reg = ([0-9.\-A-Za-z]+);
这第三个捕获型分组是是主机名. 由 一个或多个数字
,字母
, .
, -
组成.
这里需要对-
进行转义。
port
var reg = (::(\d+))?;
这第四个捕获型分组是端口号。它是由一个前置:
加上一个或多个数字而组成的序列。
path
var reg = (?:\/([^?#]*))?;
这个是另一个可选的分组,以一个/
`开始。之后的字符类[^?#]
以一个^
开始,表示这个类包含除? #
之外的所有字符。*
表示匹配0次 或多次。
query
var reg = (?:\?([^#]*))?;
这个还是一个可选分组,以一个?
`开始,它包含了一个捕获型分组,这个分组包含 0个 或多个 非 #
的字符。
hash
var reg = (?:#(.*))?;
这是最后一个可选分组,以一个#
`开始, .
会匹配除换行符以外的所有字符。
最后的$
表示字符串的结束,它保证这个url的尾部没有其他更多内容了。
以上便是parse_url的所有因子了。
这个正则表达式还可以写的更复杂,但通常不推荐这么做。
再举个例子:
var url = "http://www.ora.com:80/goodparts?q#fragement";
var result = url.split(/^(([^:\/?#]+):)?((\/\/)?([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/);
console.log(result);
短小精悍的正则表达式是最好的。
作为基础入门的介绍,写到这里就差不多了,后续内容后续会继续发布。
本大汪差不多也该收拾东西,明天回家~预祝大家?年大吉。
附文中出现的可视化工具
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。