当前位置 博文首页 > 蒋伟平:通过js正则表达式实例学习正则表达式基本语法
正则表达式又叫规则表达式,一般用来检查字符串中是否有与规则相匹配的子串,达到可以对匹配的子串进行提取、删除、替换等操作的目的。先了解有哪些方法可以使用正则对字符串来实现这些操作:
RegExpObject.test(string):
检查字符串 string 中是否有与 RegExpObject 匹配。有则返回 true,否则返回 false。
RegExpObject.exec(string):
检索字符串 string 中与 RegExpObject 匹配的值。有则返回相关结果的数组,否则返回 null。
stringObject.search(regexp):
找到字符串 stringObject 中第一个与 regexp 相匹配的子串的位置。
stringObject.match(regexp):
检索字符串 stringObject 中与 regexp 匹配的值;
如果 regexp 没有标志 g,进行非全局检索,执行结果与RegExpObject.exec方法相同;
如果 regexp 有标志 g,进行全局检索,返回 stringObject 中所有匹配的子字符串的数组。
stringObject.replace(regexp,replacement):
在 stringObject 找到与 regexp 匹配的子串,用 replacement 替换,返回新的字符串。
stringObject.split(separator,howmany):
用 separator 为边界,把 stringObject 分成数组,数组长度不能大于 howmany。
正则表达式最简单的规则就是匹配完全相同的普通字符,比如在一个字符串中,需要把一些敏感词用*号代替。声明字符串如下:
var str = '这是1个字符串,包含了我X和垃圾这2个敏感词,而且还是垃圾这个词还有2个,字符串中还包含数字345。';
声明一个简单的正则直接量,然后在上面字符串中匹配到符合规则的子串进行替换:
var reg = /垃圾/; var sResult = str.replace(reg,'**'); //输出结果 console.log(sResult);
输出的结果如图所示:
可以看到第一个 “垃圾” 子字符串被替换成**,而第二个却没有被替换。这是因为在声明正则的时候,只声明了匹配模式(匹配规则),默认只会检索到第一个匹配的子字符串。
有时候还需要给正则表达式添加修饰符,修饰符可以修改检索时匹配的执行方法,正则表达式的修饰符如下:
i - 匹配时不区分大小写
g - 全局匹配,不会在匹配到第一个之后就中止
m - 多行匹配
在刚才的正则表达式上加上修饰符 g ,就可以进行全局匹配,找到字符串中所以符合规则的子字符串进行替换,如下所示:
var str = '这是1个字符串,包含了我X和垃圾这2个敏感词,而且还是垃圾这个词还有2个,字符串中还包含数字345。'; var reg = /垃圾/g; var sResult = str.replace(reg,'**'); //输出结果 console.log(sResult);
效果符合预期,字符串中的敏感词 “垃圾” 都被修改成了 * 号。非常容易,对吧?稍微加点难度,按照字符串上的描述,还有一个敏感词 “我X” 也需要被替换。只需要把正则改一改,使用正则的分枝条件 | 把不同的匹配分隔开,有点类似于 || 运算符。如下所示:
var str = '这是1个字符串,包含了我X和垃圾这2个敏感词,而且还是垃圾这个词还有2个,字符串中还包含数字345。'; var reg = /垃圾|我X/g; var sResult = str.replace(reg,'**'); //输出结果 console.log(sResult);
好了,看到这里正则也算入门了,至少会用了。但如果想用于工作,肯定是远远不够的,在工作中不可能只匹配完全一样的字符。
要匹配各种不同的字符,就需要用到元字符(正则表达式规定的一种特殊代码)。正则表达式的元字符很多网站都列出了详细的表格,我在这里就偷点懒,不一一列出,继续说正则的实例,用到哪个再详细解释。
工作中有时候会拿到一些数据里面有很多空格,来学一个使用正则删除这些空格的小例子,如下所示:
var str = "有时候 我们拿到的 一些数据里面 , 会一有些多 余的空格,我 们一般都需要删除这些 空格。 " var reg = /\s/g; var sResult= str.replace(reg,''); //输出结果 console.log(sResult);
完美,字符串中所有的空格都删除了,不管是一个还是多个。通过上面的实例,就可以知道元字符 \s 可以匹配任意的空白符。再加上修饰符 g,所以就匹配到了字符串中所有的空格。
跟着我使用实例一个一个做,学起来会非常轻松。再来看一个工作中经常会碰到的例子,需要把字符串中所有的英文字母都删除。正则表达式中没有单独表示英文的元字符,这时候需要用到 [ ] 来表示字符集合,比如 [az] 就可以匹配到 a 和 z 这两个字母。但26个字母都写 [ ] 在里面好像有点多,所以可以用 [a-z] 这样的省写表示所有英文字母。代码如下所示:
var str = '有时候We我们拿到的Some一些数据里面, 会是中文Chinese和英文English在一起,需要删除这些英文。' var reg = /[a-z]/g; var sResult = str.replace(reg,''); //输出结果 console.log(sResult);
结果有点不符合预期,只删除了小写字母,大写字母还是纹丝不动。可以在这里再学两个知识点,一是在字符集合中把大写字母也加上,比如: /[a-zA-Z]/g ;二是多加一个修饰符 i ,可以不区分大小写,比如: /[a-z]/gi 。我就不演示了,读者可以自己试下。
把需求反过来,把所有中文给删除掉。可以在字符集合使用unicode编码的中文编码开始和结束这两个值来匹配中文,比如: /[\u4e00-\u9fa5]/g。代码如下所示:
var str = '有时候We我们拿到的Some一些数据里面, 会是中文Chinese和英文English在一起,需要删除这些中文。' var reg = /[\u4e00-\u9fa5]/g; var sResult = str.replace(reg,''); //输出结果 console.log(sResult);
再来看一个替换数字的实例,这次把字符串中的每组数字都替换成 -- 符号,代表数字的元字符是 \d ,代码如下所示:
var str = '这些中文123中间,夹杂456着一些789数字,我们1010现在要做的就是把2324这些数字都换成符号'; var reg = /\d/g var sResult = str.replace(reg,'--'); //输出结果 console.log(sResult);
看到结果,又和预期有点不一样。现在是每个数字都换成了 -- 符号,而要求是每组数字替换成 -- 符号。所以再学一个新的知识点:限定符(又叫量词)。限定符规定了匹配的重复方式,常用限定符如下所示:
字符 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
学会限定符后,把上一个例子改一改。现在要替换的一组数字且并不知道它的长度,所以加上一个限定符 + (重复一次或更多次)。如下所示:
var str = '这些中文123中间,夹杂456着一些789数字,我们1010现在要做的就是把2324这些数字都换成符号'; var reg = /\d+/g var sResult = str.replace(reg,'--'); //输出结果 console.log(sResult);
很好,符合需求,完美完成。
有时候要匹配的字符就是元字符,比如刚才用到的 +,在一个字符串中需要把限定符 + 换成中文 和 字。这时候需要用到字符转义,所谓字符转义就是在元字符前加 \ 来取消这些字符的特殊意义。代码如下:
var str = '这里有一个字符串,有正+反,高+矮,大+小这些反义词,中间的符号需要修改。'; var reg = /\+/g; var sResult = str.replace(reg,'和'); //输出结果 console.log(sResult);
再来写一个匹配日期的正则表达式,2020-10-10和2020/2/2都是正确的日期格式。作为初学者,写正则的时候可以先进行分解。比如:
2020-10-10 分解成 “4个数字1个杠1或2个数字1个杠1或2个数字”,即为 /\d{4}-\d{1,2}-\d{1,2}/
2020/2/2 分解成 “4个数字1个斜杠1或2个数字1个斜杠1或2个数字”,即为 /\d{4}\/\d{1,2}\/\d{1,2}/
这时候出现了两个分支的情况,为了看得更清楚,可以把两个分支都用圆括号 () 括起来,如:/(\d{4}-\d{1,2}-\d{1,2})|(\d{4}\/\d{1,2}\/\d{1,2})/
var str = '2020-10-10是一个日期格式'; var str2 = '2020/2/2也是一个日期格式'; var reg = /(\d{4}-\d{1,2}-\d{1,2})|(\d{4}\/\d{1,2}\/\d{1,2})/; //输出结果都是true console.log(reg.test(str)); console.log(reg.test(str2));
这里的圆括号 () 在正则表达式里面起到一个分组的作用。
看到这里,读者已经知道了正则表达式的普通字符、元字符、分枝条件、字符集合、限定符、字符转义和分组这些知识,是时候做一些真正的实例了。
来做一个修改文本框内容时验证金额功能,要求格式为数字;保留两位小数点。
具体实现步骤我就不在这里过多描述,可以参考我的另一篇文章 《原生js制作表单验证,基本的表单验证方法》 学习表单验证功能如何制作。本文还是以正则表达式的规则为主要描述内容。
分析本实例的规则也是非常简单,只有三个要求,一是必须是数字;二是必须有小数点;三是小数点后保留两位数字。要求分析完的规则,完成正则如下:
/^\d+\\.\d{2}$/
在这个正则表达式中,要新学两个元字符 ^ 和 $ 。
^ 匹配字符串的开始位置,$ 匹配字符串的结尾位置。
^\d 的意思就是必须数字开头;+ 是限定符表示重复一次或多次; \\. 表示小数点,因为小数点本身就是元字符,所以前面要多加一个反斜杠;\d{2}$ 表示结尾必须是两个数字。
这样分析完,如果还不清楚的话,可以动手完成以下代码自己看下实际效果:
<div class="form_Box"> <dl> <dt>金额:</dt> <dd><input type="text" id="verifyMoney"><span></span></dd> </dl> </div> <script> //获取input元素 var eInput = document.getElementById('verifyMoney'); //在input元素上绑定change事件 eInput.addEventListener('change',function(event){ //获取输入值 var sValue = this.value; //声明正则表达式 var reg = /^\d+\.\d{2}$/; //获取父级元素 var eParent = this.parentElement; //获取input元素后的span元素,用于存放提示信息 eSpan = eParent.getElementsByTagName('span')[0]; if(reg.test(sValue)){ //span元素上清除提示 eSpan.innerHTML = ''; }else{ //span元素上显示提示 eSpan.innerHTML = '请输入正确的金额格式,保留两位小数点'; } }); </script>
本实例模拟一个价格输入框,只能输入数字和小数点。可以通过正则表达式找到非数字和小数点的内容替换为空字符串来实现。
分析本实例的规则:一是非数字;二是非小数点。正则表达式如下:
/[^\d\\.]/g
在这个表达式中,又看到一个新的知识点:^ 字符在表达式最前面表示匹配字符串的开始位置,而在方括号中,表示匹配非字符集 [ ] 中的字符。所以正则表达式 /[^\d\.]/g 将匹配所有非数字和小数点的字符。
可以用此正则表达式找到文本框中匹配的字符替换为空字符串,看起来就像只能输入数字和小数点。具体实现代码如下:
<div class="form_Box"> <dl> <dt>金额:</dt> <dd><input type="text" id="verifyMoney"></dd> </dl> </div> <script> //获取input元素 var eInput = document.getElementById('verifyMoney'); //在input元素上绑定input事件 eInput.addEventListener('input',function(event){ //获取输入值 var sValue = this.value; //声明正则表达式 var reg = /[^\d\.]/g; this.value = sValue.replace(reg,''); }); </script>
笔者在这里再贡献一个严格的金额正则表达式,如下所示:
/^0|^\.|[^\d\.]|(?<=\.\d*)\.|(?<=\.\d{2})\d/g;
此表达式严格限制输入金额的格式,只能输入数字;不能0开头且后面不是小数点;小数点后最多只能有两位数字;只能有一个小数点;不能小数点开头。可惜有些浏览器不识别,其中还有未提及的知识点,有兴趣的读者可以自己尝试分解。
网页中经常会碰到需要填写身份证号码,提交的时候就应该先验证身份证格式是否正确。看一下身份证号码的编排规则:1-6位数字代表省市区,第一个数字不能是0;7-14位数字表示出生年月日;15-16位数字表示所在地的派出所代码;17位数字表示性别;18位数字是校检码,可以是0-9,也可以是字母X。根据身份证格式写出正则表达式如下:
/^[1-9]\d{5}[12]\d{3}((0[1-9])|(1[0-2]))(([0|1|2][1-9])|3[0-1])\d{3}([0-9]|X)$/;
再来分解表达式:
具体实现代码如下:
<