正则表达式(Regular Expression)是一种文本模式,包括普通字符元字符,用于字符串操作,比如查找、匹配等。学习正则,首先需要知道它最基础的语法、字符、用法等等,这相当于正则的砖。
第一步 学习正则基础
首先阅读一下菜鸟的基本教程:
再看看这篇文章总结巩固一下:
简单总结一下吧:
一、基本语法:
? 前面的字符0或1次 (如果有了+后面再跟一个?是非贪婪匹配,匹配最少项)
+ 前面的字符>=1次
* 前面的字符>=0次
^ 匹配字符串起始
$ 匹配字符串结尾位置 (还可结合()做分组及替换)
() 匹配一个子表达式
| 或,两项之间的选择
. 匹配除换行符\n以外的任何单字符
{n} 匹配n次
{n,} 匹配至少n次
{n,m} 匹配n到m次
\b 匹配一个单词边界
\B 匹配非单词边界
可以使用 \n 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
复制代码
二、表达形式:
//构造函数
var reg = new RegExp('along','img')
console.log(reg) --> /along/gim
//字面量方式
var reg = /a/
console.log(reg) --> /along/gim
//工厂模式
var reg = RegExp('along','img')
console.log(reg) --> /along/gim
复制代码
三、基础常用方法
- RegExp.prototype.test 检测是否包含
//作用:用来检测字符中是否含有某个内容。
var str = 'hello world';
var reg = /hello/g;
reg.test(str); ---> true 返回值:true或者false
复制代码
- String.prototype.match 匹配筛选
//作用:筛选指定字符
var str = 'hellowo12345rdle';
var reg = /[0-9]/img;
str.match(reg); ---> ['1','2','3','4','5'];
复制代码
- String.prototype.split 拆分
var str = '2019-05-12';
var reg = /-/g;
console.log(str.split(reg)) . --->["2019", "05", "12"]
复制代码
- String.prototype.replace 替换
var str = 'aadfsfsdf21AAAA324aaa';
var reg = /a/img;
console.log(str.replace(reg, '哈')) . --> 哈哈dfsfsdf21哈哈哈哈324哈哈哈
复制代码
第二步 日常练习巩固
学习了正则的基础语法,虽然不一定就能立即融会贯通,但面对一个正则表达式时,我们至少可以理解他这么写的含义了。要想将正则在日常的代码中应用得比较熟练,还需要多多的阅读练习!
在日常的业务中,我们可能更多的是上网查找一个正则的匹配规则,直接运用到代码中,比如一个身份证、手机号的校验,但是如果你完全不懂正则的规则,一是无法分辨这个规则真正匹配的目的是什么,可能是错误的规则校验,可能没有达到你的校验目的;二是也没有办法对其进行一些修改。如手机号的校验,假设以前规定是13,17,18开头的,但现在有19,16等等的情况,那么你搜索到的匹配规则,就不一定适用了。
以下为百度搜索最靠前一些常用规则校验的网址,可以看到年限都不是很新,但一些固定的匹配规则还是有必要学习巩固一下的,你能读懂这些规则具体对应的信息吗?
举个例子:身份证号码校验
// 身份证校验,能搜索到的规则很多,来看看他们具体的匹配含义
1. 最简约,其实会把X结尾的漏掉
/^\d{15}|\d{18}$/ //15位、18位纯数字
2. 疏忽了15位数的情况
/^((\d{18})|([0-9x]{18})|([0-9X]{18}))$/ // 18位身份证号码(数字、字母x结尾)
3.普通版,正常的校验,没有附加规则
/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/ // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X,大小写均可
4.根据身份证地址码、年份月份码、顺序码规则
^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$ // 18位
^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}[0-9Xx]$ // 15位
(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx])|([1−9]\d5\d2((0[1−9])|(10|11|12))(([0−2][1−9])|10|20|30|31)\d2[0−9Xx]) // 汇总
说明:
地区:[1-9]\d{5}
年的前两位:(18|19|([23]\d)) 1800-3999
年的后两位:\d{2}
月份:((0[1-9])|(10|11|12))
天数:(([0-2][1-9])|10|20|30|31) 闰年不能禁止29+
5、带上算法
...脑子记不住了,忽略,用的时候去搜吧...
复制代码
上面说到,身份证的编码生成还有其特定的规则,可以写出更复杂的正则表达式,此处便不再赘述了
感兴趣的可自行检索相关文章,如
身份证正则表达式
第三步 正则加强:()与$1,$2
的用法
参考文章:js正则表达式()和$1...$9
的理解和使用_愤怒无济于事-CSDN博客
理解:
()就是起到一个分组作用,将匹配到的放到mathches集合中,$1$9)相当于对应索引的值。可以使用()和( $1$9)来限制输入位数
应用:从案例来理解
例:只能输入1-9999正整数
<input id="digit" type="text" οnkeyup="clearInput(this)" onafterpaste="clearInput(this)">
//只能输入1-9999正整数
function clearInput(obj){
obj.value = obj.value.replace(/[^\d]/g,""); // 对于输入的^/d非数字,替换成''
obj.value = obj.value.replace(/^0.*$/g,""); // 对于0.后面无论有没有值,替换成''
obj.value = obj.value.replace(/^([1-9])(\d{3}).*$/,'$1$2'); //只能输入两个小数
} // 对于四位数,后面带小数点.的,替换成$1$2,也就是只保留四位数,不带后面小数点的部分
复制代码
例:只能输入数字和保留两位小数
<script language="JavaScript" type="text/javascript">
function clearNoNum(obj){
obj.value = obj.value.replace(/[^\d.]/g,""); // 清除非“数字”和“.”以外的字符
obj.value = obj.value.replace(/\.{2,}/g,"."); //只保留第一个小数. 清除连续多余的. 如2..3..4这种只留下2.3.4
obj.value = obj.value.replace(".","$#$").replace(/\./g,"").replace("$#$",".");
// 第一个replace只会替换第一个.然后将其他的.去掉,再将第一个转回来,为了将2.3.4这种,替换成2.34454
obj.value = obj.value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3');//只能输入两个小数,可以为负数
// -可以有或没有,然后纯数字d,然后小数点后两位数字,然后再是小数点可有可无,对这种形式,只取前面$123,
// 也就是对应三个括号-33.3类似这种。
if(obj.value.indexOf(".")< 0 && obj.value !=""){//以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额
obj.value= parseFloat(obj.value);
}
}
</script>
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
</head>
<body>
<input type="text" onkeyup="clearNoNum(this)">
</body>
</html>
复制代码
第四步 正则深入(贪婪非贪婪、捕获非捕获)
这部分的内容很多很深,我也只是有一些粗浅的理解和应用,不对之处请指正。
贪婪模式、非贪婪模式
贪婪模式、非贪婪模式 (简单记忆: 量词{m.n},?,*,+后面是否加?)
参考文章:
正则表达式之 贪婪与非贪婪模式详解(概述)_正则表达式_脚本之家
简单理解:
在正则表达式的匹配量词后面没有加?的是贪婪匹配,在使整个表达式匹配成功的前提下,会尽可能多的匹配到内容,加了?的是非贪婪匹配,当匹配完成就结束。
被匹配优先量词修饰的子表达式,使用的是贪婪模式;被忽略优先量词修饰的子表达式,使用的是非贪婪模式。
匹配优先量词包括:“{m,n}”、“{m,}”、“?”、“*”和“+”。
忽略优先量词包括:“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。
举例:
源字符串:aa<div>test1</div>bb<div>test2</div>cc
正则表达式一:<div>.*</div>
匹配结果一:<div>test1</div>bb<div>test2</div>
正则表达式二:<div>.*?</div>
匹配结果二:<div>test1</div>(这里指的是一次匹配结果,所以没包括<div>test2</div>)
复制代码
捕获匹配非捕获匹配
参考文章:
Python正则表达式教程之二:捕获篇_python_脚本之家
捕获匹配非捕获匹配 (简单记忆:括号分组是否加?: )
(…) 正常分组,捕获
(?:…) 分组,但是不捕获,也就是我们后面要用到$123排序取分组的时候,是会略过的
非捕获匹配只用来做判断,但是不作为匹配内容被捕获出来存储
(1)正向预言 ?:非捕获,相当于(x)?,但x不记在捕获中
(2)正向前瞻 z(?=x) 表示z后面一定要有x,但x不记在捕获中
(3)负向前瞻 z(?!x)表示z后面一定不要有x,但x不记在捕获中
(4)正向后瞻,负向后瞻 。。。。 js不支持
举个例子:
正向预言:
var a='3.456'
a.replace(/(\d+)(\.)(\d\d)(\d)/,'$1$2$3')
// "3.45" 保留2位小数
a.replace(/(?:\d+)(?:\.)(\d\d)(\d)/,'$1$2')
// '456' 取出小数部分
正向前瞻
var str = 'Hello, Hi, I am Hilary.';
2 var reg = /H(?=i)/g;
3 var newStr = str.replace(reg, "T");
console.log(newStr);//Hello, Ti, I am Tilary. 把后面带i的H,替换成了T
负向前瞻
var str = 'Hello, Hi, I am Hilary.';
var reg = /H(?!i)/g;
var newStr = str.replace(reg, "T");
console.log(newStr);//Tello, Hi, I am Hilary. 吧后面不带i的H,替换成了T
复制代码
学海无涯,道阻且长~~