#什么是正则
正则就是一个规则,就是处理字符串的,验证正则用的是test方法。正则的捕获用exec方法或者字符串的split,replace,match可以。
var reg = /^$/ //两个斜杠之间内容的就是正则,两个斜杠之间的都是元字符。
#修饰符&元字符
修饰符
- g (global):全局匹配
- i(ignorCase):忽略单词大小写
- m (multiline):多行匹配
元子符
[量词元字符]
- +:让前面的元字符出现1次到多次;
- ?:出现0到1次;
- *:出现0次到多次;
- {n}: 出现次;
- {n,}:出现n到多次;
- {n,m}:出现n到m次;
[特殊元字符]
- \d:匹配一个0-9之间的数字;
- \ :转义字符(把一个普通字符转变成有特殊意义的字符,或者把一个有意义的字符转换成为普通字符);
- . :除了\n(换行符)以外的任意字符;
- \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以外的任意字符;
- ():正则的小分组,匹配一个小分组(小分组可以理解为大正则中的小正则);
- ^:以某一个元字符开始;
- $:以某一个元字符结束;
- ?: :只匹配不捕获;
- ?= :正向预查;
- ?! :反向预查;
[普通元字符]
代表本身意思的就是普通元字符。
小练
//开始&&结束
var reg = /\d+/; // 只要包含即可。
var a = 'shud215512sdfsdf';
reg.test(a) =>true
var reg = /^\d+/; //^(英语发音:/ˈkærət/),在中括号里是非,在双斜杠里是以某开头
var a = 'shud215512sdfsdf';
reg.test(a) =>false
var reg = /^\d+$/;
var a = '215512sdfsdf5225';
reg.test(a) =>false //只能是某某的,这里以数字开头数字结尾,中间都是数字。
reg.test('2') =>true //^或者$只是一个修饰或者声明,不会占据字符串的位置。
// 转义 \
var reg = /^2.3$/; // .在这代表的是除了\n以外的字符都可以
var a = '2+3';
reg.test(a) =>true
var reg = /^2\.3$/;
var a = '2+3';
reg.test(a) =>false;
a = 'a.3';
reg.test(a) =>true;
//******************* 正则里面不能允许一个斜杠出现
var reg = /\\\d/;
reg.test('\\5') ==>true,// 这里两个斜杠出现的时候,不但把后面的转义还把自己也变成普通。
x|y
var reg = /^18|19$/;
reg.test() //189,18,19,1819都符合:
/*
*18或者19
*以1开头,以9结尾,中间1或8
*以18开头19结尾即可
*/
var reg = /^(18|19)$/;//这才是我们想要的
()
:正则中的分组,大正则中的小正则,在正则中可以改变一些默认优先级
。小分组第二个作用:分组引用
小分组第三个作用:分组捕获
//分组引用 :\1 ,\2 出现和第n个分组一模一样的内容
var reg = /^([a-z])([a-z])\2([a-z])$/
reg.test('foot') ==>true
[]
正则的小括号有消磁的作用
[xyz] [^xyz] [a-z] [^a-z]
// \w代表的是数字字母下划线任一个
var reg = /^[a-zA-Z0-9_]$/ // === \w
//中括号里出现的元字符,一般都代表本身含义
var reg = /^[.?+&]+$/
reg.test('...') //===true
// 里面的字符变成了本身的含义了,但是不能以(-)开头
var reg = /^\w[\w-]*$/
//要求验证18~65之间的年龄
var reg = /^[18-65]$/ //这样代码会解意为1或者8到6或者5中的任意一个字符,中括号中的18不是数字18,而已1或者8([xyz]),并且当前这个是违法的,因为8~6这个范围不存在。
//所以我们要给它分组
//18~19
//20~59
//60~65
var reg = /^((18|19)|([2-5]\d)|(6[0-5]))$/ // ==
常用的正则编写
有效数
- 可能是正数,可能是负数 12 -12
- 整数或者小数 1 0.2
- 只要出现小数 后面至少一位数字
- 小数点前面必须有数字
var reg = /^-?(\d|([1-9]\d+))(\.\d+)? $/
/*
*-? 负号可有可无
*(\d|([1-9]\d+)) 一位或者多位
* (\.\d+) 小数部分可有可无。有的话必须跟一位数字
*/
手机号
手机号的规范有:
- 11位数字
- 1开头
var reg = /^1\d{10}$/
姓名
// /^[\u4E00-\u9FA5]$/ 中文汉字的正则
var reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10})? $/
邮箱
var reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
//分析
/*
*以数字字母下划线开头
* @前面可以是数字字母下划线 - . 这些符号
* 不能让-和. 连续出现,出现后面必须跟数字字母下划线
*/
详细解析:
- [A-Za-z0-9]+ => @163
- ((.|-)[A-Za-z0-9]+)* => @sss-ddd-sss-dd.com.cn
- .[A-Za-z0-9]+ => .com.cn
身份证
- 18位
- 前17位必须是数字
- 最后一位可以是数字或者x
// 130947199205022827 - 前6位是省市县 130947
- 接下来8位 出生年+月+日 19920502
- 倒数第二位数字 奇数代表男,偶数代表女
//简单写一下
var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|x)$/
这样写不仅可以匹配。并且以后捕获的时候可以把小分组里的结果也捕获到—“分组捕获”
正则捕获
exec
把当前字符串中符合正则的字符捕获到
RegExp.prototype:exec
实现正则捕获的方法
var str = '我很好2018,2019更好'
var reg = /\d+/
reg.exec(str)
当正则捕获的时候:
- 先去验证当前字符串和正则是否匹配,不匹配返回null
- 如果匹配,从字符串左边开始向右匹配。并把匹配结果返回
exec
匹配结果格式
1 获取结果是个数组
2 数组中的第一项是当前匹配大正则在字符串中匹配到的结果
3 index是匹配的索引
4 input 是当前正则操作的原始字符串
5 如果有小分组,那从第二项中就开始是每个小分组了
举个例子:
var str = '130947199205022827'
var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|x)$/
reg.exec(str)
// ["130947199205022827", "130947", "1992", "05", "02", "2", "7", index: 0, input: "130947199205022827"]
正则匹配捕获有懒惰性
正则为什么会存在懒惰性?
正则本身有一个属性:lastIndex—(下一次正则在字符串中匹配查找的开始索引)
var str = '我很好2018,2019更好'
var reg = /\d+/
reg.exec(str) //第一次拿到2018
reg.exec(str) //第二次拿到2018
console.log(reg.lastIndex) // =>0
console.log(reg.exec(str)[0])// =>2017
console.log(reg.lastIndex)// =>0
//捕获的时候始终从第一个开始
解决正则懒惰性,在正则末尾加修饰符g,每一次exec结束后,浏览器会默认把lastIndex进行修改(手动修改不认的)
这样就可以匹配到所有内容了,
不过exec有自己的局限性,执行一次只能捕获到一个结果(即使加了g)
不过我们可以自己封装一个多次执行的方法
RegExp.prototype.myExecAll = function myExecAll(){
var str = arguments[0] || ''
var result = []
//判断有没有g,没有执行一次,有执行多次
if(!this.global){
return this.exec(str)
}
var ary = this.exec(str);
while(ary){ //看ary是不是null
result.push(ary[0])
ary = this.exec(str)
}
return result
}
match
上面讲了自己封装的一个匹配多次的方法,但这个问题人家早就解决了,就是match方法
var str = '我很好2018,2019更好'
var reg = /\d+/g
str.match(reg)
//["2018", "2019"]
使用字符串中的match捕获
- 加修饰符g,匹配所有政治匹配的内容
- 如果没有g, 执行一次只能匹配第一个,跟exec执行一样。
局限性
在加g的情况下执行match,只能把大正则的捕获到,小正则的自动忽略