Introduction
This is an article about regular in chinese, for it is hard to understand, so it is better recorded in
mother language.This was learned from Mount Everest public class and this is to be continued. By the way,please forgive me to say that regular is really fabulous.
正则
什么是正则?
正则就是一个规则,用来处理 字符串
的规则
1、正则匹配
编写一个规则,验证某个字符串是否符合这个规则,正则匹配使用的是 test 方法2、正则捕获
编写一个规则,在一个字符串中把符合规则的内容都获取到,正则捕获使用的方法:正则的exec方法、字符串中的split、replace、match等方法都支持正则;
1 | var reg = /^$/; // => 两个斜杠中间包含一些内容就是正则,两个斜杠之间包含的全部内容都是元字符 |
正则的元字符和修饰符
任何一个正则都是由 元字符 和 修饰符 组成的
修饰符
g(global); 全局匹配
i(ignoreCase); 忽略大小写
m(multiline); 多行匹配
元字符
[量词元字符]
+:让前面的元字符出现一到多次
?:出现零到一次
*:出现零到多次
{n}:出现n次
{n, }:出现n到多次
{n, m}:出现n到m次
[特殊意义的元字符]
\:转义字符(把一个普通字符转变为有特殊意义的字符,或者把一个有意义字符转换为普通的字符)
.:除了\n(换行符)以外的任意字符
\d:匹配一个0~9之间的数字
\D:匹配任意一个非0~9之间的数字(大写字母和小写字母的组合正好是反向的)
\w:匹配一个 0~9或字母或_
之间的字符
\s:匹配一个任意空白字符
\b:匹配一个边界符
x|y:匹配x或者y中的一个
[a-z]:匹配a-z中的任意一个字符
[^a-z]:和上面相反,匹配任意一个非a-z中的字符
[xyz]:匹配x或者y或者z中的一个字符
[^xyz]:匹配除了xyz以外的任意字符
():正则的小分组,匹配一个小分组(小分组可以理解为大正则中的一个小正则)
^:以某一个元字符开始
$:以某一个元字符结束
?::只匹配不捕获
?=:正向预查
?!:负向预查
…
除了以上特殊元字符和量词元字符,其余的都叫做普通元字符;:代表本身意义的元字符
元字符详细解读
1 | var reg = /\d+/; |
\
1 | var reg = /^2.3$/; |
x|y
1 | var reg = /^0|1$/; |
():正则中的分组,也可以理解为一个大正则中的一个正则(包起来的部分是一个整体):在正则中我们可以使用小括号
改变一些默认的优先级
;
小分组还有第二个作用:分组引用
小分组的第三个作用:分组捕获
1 | var reg = /^[a-z]$/; |
[]
[xyz][^xyz][a-z][^a-z]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 // => \w:数字字母下划线中的任意一个字符
var reg = /^[a-zA-Z0-9_]$/; // => 等价于 \w
// => 中括号中出现的元字符,一般都代表本身的含义
var reg = /^[.?+&]+&/; // => 里面的四个元字符都是本身含义,例如:点就是小数点了,不是所谓的任意字符
reg.test('您好'); => false
reg.test('...'); => true
reg.test('?+'); => true
var reg = /^[a-z]$/;
reg.test('-'); => false
reg.test('a'); => true
// => 需求:描述样式类名的规则(数字、字母、下划线、-),并且不能以-开头
var reg = /^[\w-]+$/;
var reg = /^[0-9a-zA-Z_--]+$/; // => 没有处理以-开头的情况
reg.test('-bb'); => true
var reg = /^\w[\w-]*$/;
1 | // => 需求:验证18~65之间的年龄 |
1 | var reg = /^[\]$/; => 报错 |
常用的正则表达式编写
验证是否为有效数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 可能是正数,可能是负数 12 -12
* 整数或者小数 0 12 0.2 12.5 -12.3
* 只要出现小数点,后面至少要跟以为数字
* 小数点前面必须有数字
**/
var reg = /^-?\d+(\.\d+)?$/;
var reg = /^-?(\d|([1-9]\d+))(\.\d+)?$/;
/**
* -? 负号可有可无
* (\d|([1-9]\d+))
* \d 一位数可以是任何值
* ([1-9]\d+) 多位数不能以零开头
* (\.\d+)? 小数部分可有可无,有的话点后面必须跟一位数字
电话号码
1 | /** |
用户名:真实姓名
1
2
3
4
5/**
*
**/
//=> /^[\u4E00-\u9FA5]$/ 中文汉字的正则
var reg = /^[\u4E00-\u9FA5]{2, 5}(·[\u4E00-\u9FA5]{2, 5})?$/;
邮箱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
/**
* \w+ =>以数字字母下划线开头
* @前面可以是 数字、字母、下划线、-、. 这些符号
* ((-\w+)|(\.\w+))* => 不能把 - 和 . 连续出现,出现一次后面必须跟数字字母下划线
* @ 后面的部分支持
* 企业邮箱
* .com.cn 多域名情况
*
* [A-Za-z0-9]+ => @153.com.cn
* ((\.|-)[A-Za-z0-9]+)* =>
* \.[A-Za-z0-9]+ =>
**/
@163.com.cn
@test-test-test-test.com.cn
身份证号码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/**
* 18位
* 前17位必须是数字
* 最后一位可以是数字或者X(X代表数字10)
*
* 362202199308018888
* 前六位:省市县 362202
* 接下来八位 出生年+月+日
* 倒数第二位数字 奇数代表男 偶数代表女
**/
var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;
// => 这样写不仅可以匹配,而且以后再捕获的时候,不仅可以把大正则匹配的结果捕获到,里面每一个小分组(小正则)匹配的结果也可以单独的捕获到"分组捕获"
// => 年 1950~2017
// => 第一段 1950~1999
// => 第二段 2000~2017
// => 00~09
// => 10~17
// => /^((19[5-9]\d)|(20((0\d)|(1[0-7]))))$/
正则捕获
把当前字符串中符合正则的字符捕获到
RegExp.prototype:exec
实现正则捕获的方法
1 | var str = ''; |
正则捕获存在懒惰行
执行一次exec捕获到第一个符合规则的内容,第二次执行exec,捕获到的依然是第一个匹配的内容,后面匹配的内容不管执行多少次exec都无法捕获到
解决正则捕获的懒惰性;
在正则的末尾加修饰符g(全局匹配)
1 | //=> 正则为什么会存在懒惰性? |
exec有自己的局限性:执行一次exec只能捕获到一个和正则匹配的结果(即使加了修饰符g),如果需要都捕获到,我们需要执行N次exec方法才可以
下面封装的myExecAll方法,目的是执行一次这个方法,可以把当前正则匹配到的全部内容都捕获到
1 | RegExp.prototype.myExecAll = function myExecAll() { |
使用字符串方法match实现捕获
1 | var reg = /\d+/g; |
使用字符串的match捕获:
1、如果正则加了修饰符g,执行一次match会把所有正则匹配的内容捕获到;
2、如果没有加修饰符g,执行一次match只能把第一个匹配的结果捕获到;局限性:
在加了修饰符g的情况下,执行match方法只能把大正则匹配的内容捕获到,对于小分组捕获的内容方法给其自动忽略了
1 | var str = 'my name is {0}, i am {1} years old~, 2018'; |
14、使用test也可以实现正则的捕获
不管是正则的匹配还是正则的捕获,在处理时候的原理是没区别的:
从字符串的第一个字符向后查找,找到符合正则规则的字符,如果可以找到,说明正则和字符串匹配(test检测返回true、exec捕获返回捕获的内容),如果找到末尾都没有匹配的,说明正则和字符串不匹配(test检测返回false、exec捕获返回null)
如果正则设置了修饰符g,不管使用test还是exec中的任何方法,都会修改lastIndex值(下一次查找是基于上一次匹配结果的末尾开始查找的)
1 | var reg = /\{(\d+)\}/g; |
使用test不仅可以找到匹配的内容,也能像exec一样,把找到的内容获取到
test返回结果是true/false,所以靠返回结果肯定不行
1 | var reg = /\{(\d+)\}/g; |
15、所有支持正则的方法都可以实现正则的捕获(一般都是字符串方法),
字符串中常用的支持正则的方法:
match
split
replace
…
1 | var str = '?name=123&age=8&lx=test'; |
replace
replace:字符串中原有字符的替换
str.replace(old, new)
1 | var str = 'test123you123' |
replace原理:
1、当replace方法执行,第一项传递一个正则
正则不加g: 把当前字符串中第一个和正则匹配的结果捕获到,替换成新的字符
正则加g: 把当前字符串中所有和正则匹配的内容都分别的捕获到,而且每一次捕获,都会把当前捕获的内容替换为新字符
Words in the end
Here recommands a very good article to make you better understand regular: