javascript中正则表达式语法详解


Posted in Javascript onAugust 07, 2020

好久都没有写博客了,主要是太懒了,尤其是在阳春三月,风和日丽的日子,太阳暖暖的照在身上,真想美美的睡上一觉。就导致了这篇博客拖到现在才开始动笔,javascript的正则这一块也不是什么新的东西,主要是以前本人一遇到写正则的需求就开始头大,头疼,网上剽窃,东拼西凑,反正就是各种不适应,所以我打算系统的把正则表达式看一遍,一来是自己有所提升,这一块知识点的查漏补缺,二来是给大家分享一下。好了,下面我们直接进入主题:

正则是匹配字符串特定模式的一种表达式,官方是这样说的,但我的理解不外乎就是匹配字符窜嘛,举个例子大家就明白了。比如我们要验证邮箱,试想一下如果我们不用正则来匹配,直接用代码,循环,判断各种捣鼓来验证还真是一件非常麻烦的事情。如果用正则怎么来做了,这里为了照顾小白(当然我也是重小白走来的,所以小白很单纯,小白很善良,小白很伟大)我就写伪正则来描述: 所有0-9或者a-z或者A-Z的字符出现一次到多次 加上(就是前面出现了的所有0-9...的字符跟上) "."或者"_"出现0次或者1次,然后在跟上 "@"符号 跟上 xxx.xx这种格式。 不知道我这样来描述各位亲有没有明白一点,不明白也不要紧,这里我只是随便举个列子,提一下,在下文的某个位置我会专门一步一步分析几个非常复杂的正则表达让大家能够很快的明白正则的语义。

上面举了一个邮箱地址的正则表达式,比如这一窜 /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/ ;要看懂坑爹的这一窜,还得从基础一步一步的来。首先给大家介绍javascript经常使用正则的对象和方法:

RegExp 这个是正则对象, 比如匹配字符串"1234"中的"23"可以这样玩: (new RegExp("23")).test("1234"); //out true;

当然正则对象还有一种写法:

var reg = /23/; reg.test("1234") //out true;


RegExp.test(String) ; //这个方法上面的用上了,匹配字符串是否为指定格式


RegExp.exec(String); //返回查询的值




var str = "123 aa cat Cat caT";



var reg = /cat/i;



reg.exec(str); // out "cat" 如果有则返回,没有的话就返回null


String.search(RegExp) ; // 返回索引位置,类似indexOf()




var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,";

 var reCat = /cat/gi;

 alert(data.search(reCat)); //out "23"


String.replace(RegExp, String); // 将字符串替换成另外一个字符窜,RegExp指定的格式,String要替换的字符串




var str = "1234aa67aa89";

 var reg = /aa/gi;

 str.replace(reg, "") ; //out "12346789"


String.split(RegExp) ; // 将字符串拆分成数组




var str = "1234aa67aa89";

 var reg = /aa/gi;

 str.split(reg) ; //out [1234, 67, 89]


String.match(RegExp); //将指定格式的字符串以数组的方式返回




var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,";

 var reCat = /cat/gi;

 var arrMactches = data.match(reCat); // out ["Cat", "cat"]

上面的的方法是在字符串过滤操作中经常用到的方法, 当然还有一些我没有全部列举出来,用到了在去差API也不迟,好了我们熟悉了操作正则的这些方法之后我们紧接着正则表达式了,所谓表达式意思就是用一些字符按照先后顺序组合在一起表示的一层含义,所以我们先要重正则表达式的元字符说起,其实元字符就相当于javascript语言的关键字,比如你定义变量不能这样干 var if = "xxxx"; 正则有一下一些元字符:{ [ ^ | $ ] } ? * + . 这些都是正则的元字符,这里我就不解释意思了,用到了时候再来分析。如果大家想知道可以找度娘

字符类

字符类是用于测试字符串的组合, 将一些字符放入方括号中,就可以有效的告诉正则表达式去匹配第一个,第二个,第三个...比如/[abc]/,这个又称之为简单类

简单类:

var str = "cat 123 caT 234 cAt 345 CaT";
 var reg = /cat/gi;
 
str.match(reg) ; //out ["cat", "caT", "cAt", "CaT"]

负向类和范围类: 这里要解释下"^" "-"这两个符号, "^"这个符号的意思就是取反,而"-"是范围, g表示全局,i表示忽略大小写,/[^2-3a-z]+/gi 所以这句话的意思就是: 除了2到3和a到z的所有字符出现1次到多次,并且在全局中忽略大小写。其实细心的看官这里还会发现一个知识点, 2-3a-z这一句其实是一个组合,又称之为组合类,下面的这个实例就用到了正则的几个知识点: 1.负向类,意思就是取反; 2. 范围类; 3.组合类,相当于逻辑运算符的并且&&

var str = "cat123caT234cAt345CaT";
 var reg = /[^2-3a-z]+/gi;
 
str.match(reg); //out ["1", "4", "45"]

  预定义类:

代码    等同于     匹配
.     [^\n\r]     除了换行和回车符之外的任意字符\d    [0-9]     数字\D    [^0-9]     非数字字符\s    [\t\n\x0b\f\r]   空白字符\S    [^\t\n\x0b\f\r]   非空白字符\w    [a-zA-Z_0-9]    单词字符,所有的字符数字下划线\W    [^a-zA-Z_0-9]   非单词字符

量词:量词是可以指某个特定模式出现的次数,可以是硬性量词,比如某个字符出现三次,也可以是软性量词,比如某个字符至少出现一次。正则中的量词有以下这些

贪婪量词:

? 出现零次到一次

+ 至少出现一次或者多次

* 出现0次到多次

{n} 出现n次

{n,m}出现n次到m次

{n,} 至少出现n次或者n+次

说道量词的话有贪婪, 惰性和支配量词,以上的这些量词都是贪婪量词,由于javascript正则引擎对支配量词支持不是很好,所以我们这里重点来说贪婪和惰性量词,先把惰性量词列出来之后在来说说他们的关系和区别

惰性量词:

?? 出现零次到一次

+? 至少出现一次或者多次

*? 出现零次到多次

{n}? 出现n次

{n,m}? 出现n次到m次

{n,}? 至少出现n次或者n+次

贪婪量词在匹配字符串的时候首先看是否匹配字符串,如果没有找到匹配的则去掉字符串中最后一个字符再次尝试,整个过程一直重复,直到字符串为空时停止。而惰性量词正好相反,首先查看字符串中第一个字符是否匹配,否则在读入下一个字符在进行匹配,直至重复这个过程到读入整个字符窜都不匹配时停止。可能说了这些多还是不太明白,下面我会举个例子帮助大家理解

var str = "abbbaabbbaaabbb1234";
   var re1 = /.*bbb/g; //贪婪匹配
   var re2 = /.*?bbb/g; //惰性匹配
   alert(str.match(re1));
   alert(str.match(re2));

亲,你觉得第一个alert会输出什么呢,如果是[abb, aabbb, aaabbb]的话的, 那么恭喜你答错了,前面说过*是贪婪量词,它在匹配的时候会首先匹配整个字符串,是从字符串的尾部操作的,当去掉字符1的时候就发现剩下的字符串"abbbaabbbaaabbb"已经达到它匹配的要求了,所以它返回的结果就是字符串"abbbaabbbaaabbb", 而第二个alert为啥子会打印[abbb,aabbb,aaabbb]呢,我们再来一步一步的看,这个是惰性匹配,所以它在匹配字符串的时候是从字符串开始的部分取出第一个字符进行匹配,发现不行,在取下一个,还是不行,直至取到了"abbb".好,现在发现匹配了,然后将这个装进数组, 在从剩下的字符串里面取,直至最后将符合指定模式的子字符串装进数组,所以最后就返回[abbb,aabbb,aaabbb]。只要稍微花点心思动动手还是很容易就理解了。好了,关于正则的量词的一些知识点就讲到这里,万里长征才走一半,下面接到说正则的复杂模式,上面说到的字符类那一块都是正则的简单模式,只能做一些简单的字母,数字,汉字,长度等效验,如果在掌握了下面的复杂模式就可以非常牛逼的匹配各种复杂,蛋痛的字符串模式了,比如邮箱,身份证验证,标签过滤,包括jquery类选择器,sizzle引擎过滤器。好了,直接切入主题吧:

复杂分组

分组模式:分组模式就那么回事我用一个例子或许你一下子就豁然开朗了

//如果要匹配"andand"的怎么做呢,你也许会说可以这样干
   var str = "asdfandandcxhksdf";
   var reg = /andand/gi;
   alert(reg.test(str)); //output true
   //好的,亲,这样匹配也是可以的,但是有不知道多少and怎么办呢,
   //不可能全部加在正则表达式里面吧,此时分组的便捷性就体现出了
   //出了它的优势,我们可以这样干:
   var reg = /(and){2}/g; //注意这里()是元字符分组的意思,{2} 是量词,贪婪量词

捕获分组模式:指的是RegExp.$1这个属性的值,这个值就是正则中一个分组的值,在这个对象RegExp中,定义了最多支持RegExp.$1-RegExp.$100个分组值,还是来个例子吧

var str = "asdffirstfirstsecondsecond1234";
    var reg = /(first){2}(second){2}/gi;
    reg test(str); // 要必须匹配之后才有下面的值
    alert(RegExp $1); //output "first"
    alert(RegExp $2); //output "second"

非捕获分组模式:上面说了捕获分组,那非捕获分组其实就是不让RegExp.$1引用了,这里要说一点的是在捕获分组中RegExp.$1会创建正则的反向引用的存储空间,所以在进行捕获分组时会有更多的空间开销,还会降低匹配速度。那现在晓得非捕获分组的好处了吧。简单的说就是在正则表达式()里面加上一个问号和冒号/(?:first)/,语法就是这样的,还是看代码吧

var str = "#123456789";
    var reg = /#(?:\d+)/;
    reg.test(str);
    alert(RegExp.$1);  //output "" 注意这里取消了反向引用就为空了

候选模式:候选我的理解就是或者,举个例子,比如你要对一个表达式同时匹配"red", "black"的话怎么做呢, 如果是在以前的话就要写两个正则来进行分别匹配,而加入了候选就可以非常方便的操作了,还是上代码吧

var str1 = "111red222";
   var str2 = "111black111";

   var reg = /(red|black)/;
   alert(reg.test(str2)); //output true
   alert(reg.test(str1)); //output true

前瞻模式:有时候我们希望某个字符分组出现在另外一个字符分组之前才去捕获,这相当于是在正则里面做判断了, 果然是高级功能,灰常强大,我在写正则的时候也没有用到过, 只是书上都说了, 我还是把它搬到这里来出哈风头。 上代码吧

/*
    *前瞻又分为正向前瞻和反向前瞻
    *下面我会用代码加注释的方式加以描述
    */
    //正向前瞻
    var str1 = "bedroom";
    var str2 = "bedding";
    var reg = /(bed(?=room))/; //符号?=来表示正向前瞻,表示在字符串"bedroom"中如果bed后面有room的字符才捕获,顺序执行
    alert(reg.test(str1)); //output true
    alert(RegExp.$1);  //output "bed" 捕获到反向引用bed字符串
    alert(reg.test(str2)); //output true
    //反向前瞻
    var reg = /(bed(?!ing))/; //符号?!来表示反向前瞻,表示在字符串"bedding"中如果有"ing"子字符串才捕获,逆序执行
    alert(reg.test(str2)); //output true
    alert(RegExp.$1);  //output "bed" 捕获到反向引用bed字符串
    alert(reg.test(str1)); //output true
    alert(RegExp.$1);
    /*以上代码如果各位亲测试不通过的话那就是正则引擎不支持前瞻*/

边界模式:这个模式很重要也很常用,比如去掉字符串的首尾空格,那下面说说几种边界的可能:

^行的开始 $行的结尾 \b单词的边界 \B非单词的边界

//用一个例子来说明边界
   var str = " xiaoming  "
   var reg = /(^\s+)|\s+$/g; //(^\s+)去除字符串开始位置的空格,\s+$去除字符串尾部空格,|这个符号想必不用我说了吧,候选
   var str = str.replace(reg, "");
   alert(str); //output "xiaoming"

多行模式:这个也是正则复杂模式里面最后一个模式了,也不经常用,不管你信不信,反正我是信了,还是直接来看代码吧

//请看下面这个实例,\n在前面的预定类,表示换行
   var str = "first\nsecond\nthread";
   var reg = /^(\w+)/g;
   alert(str.match(reg)); //output 若不指定m行的话就输出"first"
   var reg = /^(\w+)/gm;
   alert(str.match(reg)); //output [first, second, thread]

到目前为止正则表达式的语法,规则各种都已经说完了,如果各位小白认真的看到这里,我们在来分析文章开头说的邮箱验证表达式就非常容易了。好,现在我们就来一步一步的分析那个非常蛋痛的表达式,首先我们要来拆分这段表达式,我会用不同的颜色来表示这段表达式的每一段,这里就用到了一种思想,分而治之,太复杂的东西不利于直观的表达某些东西,所以拆分,打碎,各个击破:

/^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/

1.([a-zA-Z0-9]+[_|\_|\.]?)* 这一段表示的是一个分组,分组()里面首先是[a-zA-Z0-9]意思是匹配字符串大小写字母数字,后面紧跟一个+,这个是贪婪量词,1次到多次,前面提到过的。[a-zA-Z0-9]+而这一段的意思就是说大小写字母数字匹配1次到多次,[_|\_|\.]?而这个呢是符号"_"或者"."出现0次到一次。整个这段表达式的意思就是所有大小写字母数字出现1次到多次,紧接着符号"_"和"."出现0次到一次,在把这两个条件加起来成为一个组,这个组的格式又可以出现0次到多次。

2.[a-zA-Z0-9]+ 这段就不用说了吧,上面也说了就是大小写字符数字出现1次到多次

3.@([a-zA-Z0-9]+[_|\_|\.]?)* 这个理解起来就简单了,以字符@开头上面那个分组出现0次到多次的这个格式

4.\.[a-zA-Z]{2,3} 这个表达式呢还是比较容易,也是以字符"."开头所有大小写字母出现两次或者三次

5./^$/ 这两个符号是表示从字符串的开始匹配到行的结束。

看到这里大家是不是对正则表达式的认识更深了一些呢, 如果还不行话在给大家分析一个实例吧 /^((0?[1-9])|((1|2)[0-9])|30|31)$/ 这个正则的意思是验证一个月的31天,正确格式是01、09和1、31。首先我们还是来拆分 /^((0?[1-9])|((1|2)[0-9])|30|31)$/

1.首先这个表达式中出现了三个黑色的"|"候选符号,意思就是说可以匹配四种情况

2.(0?[1-9]) 这个表达式是匹配 0出现0次或者一次紧接着跟上数字出现一次,这是一种情况,如:01, 09, 1, 9这些

3.((1|2)[0-9]) 这个分组表示的是1或者2出现一次紧接着跟上0-9出现一个,又是一种情况,如:10,19,20,29

4.30|31 这个就更简单了,30或者31只能出现一次。

到此这篇关于javascript中正则表达式语法详解的文章就介绍到这了,更多相关javascript正则表达式内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
浅谈Javascript鼠标和滚轮事件
Jun 27 Javascript
Jquery index()方法 获取相应元素索引值
Oct 12 Javascript
JS保留两位小数,多位小数的示例代码
Jan 07 Javascript
基于AngularJS实现页面滚动到底自动加载数据的功能
Oct 16 Javascript
Position属性之relative用法
Dec 14 Javascript
Jquery EasyUI实现treegrid上显示checkbox并取选定值的方法
Apr 29 Javascript
浅析ES6的八进制与二进制整数字面量
Aug 30 Javascript
JavaScript中setTimeout的那些事儿
Nov 14 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
Jan 19 Javascript
微信小程序 设置启动页面的两种方法
Mar 09 Javascript
jQuery实现获取选中复选框的值实例详解
Jun 28 jQuery
Vue常用指令详解分析
Aug 19 Javascript
vue 子组件修改data或调用操作
Aug 07 #Javascript
浅谈vue生命周期共有几个阶段?分别是什么?
Aug 07 #Javascript
使用纯前端JavaScript实现Excel导入导出方法过程详解
Aug 07 #Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
Aug 07 #Javascript
javascript前端和后台进行数据交互方法示例
Aug 07 #Javascript
javascript解析json格式的数据方法详解
Aug 07 #Javascript
Vue触发input选取文件点击事件操作
Aug 07 #Javascript
You might like
PHP 和 XML: 使用expat函数(一)
2006/10/09 PHP
PHP加密函数 Javascript/Js 解密函数
2013/09/23 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
WordPress中用于获取文章作者与分类信息的方法整理
2015/12/17 PHP
PHP图形操作之Jpgraph学习笔记
2015/12/25 PHP
PHP mysqli_free_result()与mysqli_fetch_array()函数详解
2016/09/21 PHP
通过chrome浏览器控制台(Console)进行PHP Debug的方法
2016/10/19 PHP
PHP笛卡尔积实现原理及代码实例
2020/12/09 PHP
关于jQuery的inArray 方法介绍
2011/10/08 Javascript
获得所有表单值的JQuery实现代码[IE暂不支持]
2012/05/24 Javascript
JavaScript 用cloneNode方法克隆节点的代码
2012/10/15 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
JS打开层/关闭层/移动层动画效果的实例代码
2013/05/11 Javascript
js实现倒计时时钟的示例代码
2013/12/17 Javascript
如何正确使用javascript 来进行我们的程序开发
2014/06/23 Javascript
JS定义网页表单提交(submit)的方法
2015/03/20 Javascript
基于Jquery实现焦点图淡出淡入效果
2015/11/30 Javascript
js日期插件dateHelp获取本月、三个月、今年的日期
2016/03/07 Javascript
vue2.0使用swiper组件实现轮播效果
2017/11/27 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
2018/02/08 Javascript
vue安装和使用scss及sass与scss的区别详解
2018/10/15 Javascript
Vue常用的几个指令附完整案例
2018/11/06 Javascript
Nodejs + Websocket 指定发送及群聊的实现
2020/01/09 NodeJs
vue-cli+webpack项目打包到服务器后,ttf字体找不到的解决操作
2020/08/28 Javascript
[54:29]2018DOTA2亚洲邀请赛 4.7 淘汰赛 VP vs LGD 第二场
2018/04/09 DOTA
极简的Python入门指引
2015/04/01 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
33个Python爬虫项目实战(推荐)
2019/07/08 Python
基于django ManyToMany 使用的注意事项详解
2019/08/09 Python
PyTorch中topk函数的用法详解
2020/01/02 Python
浅谈h5自定义audio(问题及解决)
2016/08/19 HTML / CSS
建材业务员岗位职责
2013/12/08 职场文书
关于毕业的广播稿
2014/01/10 职场文书
元旦晚会邀请函
2014/01/27 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
Python docx库删除复制paragraph及行高设置图片插入示例
2022/07/23 Python