【关于Javascript】--- 正则表达式篇

Jerry

基础知识

一、元字符

\b 单词边界
\d 数字 [0-9]
\w 英文 数字 下划线  [a-z0-9_]
\s 空白字符[\t\v\n\r\f] 
    \t水平制表符,
    \v垂直制表符,
    \n换行符,
    \r回车符,
    \f换页符

反义
\B 非单词边界
\D [^0-9]
\W [^a-z0-9_]
\S 非空白字符 [^\t\v\n\r\f]
.   任意字符 少用

.* 任意数量的不包含换行的字符 贪婪匹配
.? 懒惰 非贪婪匹配

\u4e00-\u9fa5 中文

二、量词

{m,n} 匹配m-n次,优先匹配m次
{n,}  匹配n或以上次
{n}   匹配n次
?     0或1,有或无 等于{0,1}
+     1或以上等于{1,}
*     0或n都可以 任意 等于{0,}


eg:
/\d?/            //匹配1或0个数字
/\d{2,4}/        //匹配2到4个数字
/\s+java\s+/     //匹配有1个或多个空格的字符串java
/[^(]*/          //匹配1个或多个左括号
/^[^\.]/         //匹配以非.开头的

三、集合 字符类

[abc]    匹配a/b/c任意字符 
[^abc]   匹配除了abc外的任意字符  

[a-z]    匹配a到z任意字符 
//注意:里面的-代表的是范围 例如
'ahd-fj-k'.replace(/[a-z]/g,'A')   //输出 》AAA-AA-A
//如果我想把斜杠也替换了呢 有两个方法 
    1. 利用转义符\
    'ahd-fj-k'.replace(/[a-z\-]/g,'B')   //输出BBBBBBBB
    2. 后面加多一个-
    'ahd-fj-k'.replace(/[a-z\-]/g,'B')   //输出BBBBBBBB

//() 在集合里面默认被转义了 like this 
//'(122)do('.replace(/[(\d)]/g,'A')  输出 AAAAAdoA  
//具体被转义范围不确定 欢迎普及补充 
 

四、分支

123|34|567 //匹配123或34或567

五、边界 开始结束

^ //代表开始 在[]代表非
$ //代表结束

六、修饰符

g //全局匹配 不写的话匹配完第一个就停止
i //忽略大小写
m //忽略换行
//上面3可叠加使用

七、贪婪模式和非贪婪模式

js默认贪婪模式即最大可能的匹配
想要改成非贪婪模式在量词后面加个?

例子:

'123456789'.replace(/\d{3,6}/,'XX') //输出XX
//贪婪模式先匹配了最多的 6个数字》X 剩下3个数字也算是符合就再多一个X
'123456789'.replace(/\d{3,6}?/,'XX') //输出XXX
//非贪婪模式 优先匹配了最低要求的3个数字一次 〉 3个X

八、分组与引用与捕获

分组是正则中非常强大的功能 可以让上面提到的量词作用与一组字符。

语法:

(内容) : 识别成为可捕抓分组
(?:内容) : 识别成为非捕抓分组

图片描述
clipboard.png

/([0-9])[a-z]+\1{3}/.test('2aa222') //true

/([0-9]+)[a-z]+\1/.test('12aa12')   //true
/([0-9]+)[a-z]+\1/.test('12aa13')   //false

//这里需要注意一个问题。分组"\1"表示的并不是多个数字,而是和对应分组一模一样的数字

/<([a-z]+)>.*<\/\1>/.test('sdlk<div>sdjks</div>sdkl')
// true 

并不是所有用()起来的就能被捕抓成为分组的。
下面就要说到 非捕抓分组可以提高性能和简化逻辑
用法:

**(***) //识别成为可捕抓分组
(?:***) //识别成为非捕抓分组**

例子: 
把a1b2c3d4里面的数字都+1
'a1b2c3d4'.replace(/(\d)/g,function($1){
return $1*1+1
})
//输出 a2b3c4d5

把2015-12-25 格式成 12月25日2015年
'2015-12-25'.replace(/(\d{4})-(\d{2})-(\d{2})/g,'$2月$3日$1年')  
//输出 12月25日2015年

非捕抓例子:
'2015-12-25'.replace(/(\d{4})-(?:\d{2})-(\d{2})/g,'$2月$3日$1年') 
//第二个()里面有?:  所以它不被捕抓成分组。 于是$1对应着2015, $2对应着25
//输出 25月$3日2015年  

九、前瞻

正则表达式从文本头部想稳步开始解析,文本尾部方向,称为“前”。
简单理解为 从左到右

前瞻就是 向前检查是否属于断言
后顾/后瞻方向相反 但是javascript不支持后瞻。

名称正则含义
正向前瞻exp(?=assert)exp的后面是assert
负向前瞻exp(?!assert)exp的前面面是assert
正向后顾exp(?<=assert)Javascript不支持
负向后顾exp(?<!assert)Javascript不支持

注意:断言部分只是判断条件,不参与匹配

clipboard.png

正向前瞻 例子:
'a2*3w4sb'.replace(/\w(?=\d)/g,'X') //输出X2*3X4sb
//主角是\w 只对它进行匹配。
//(?=\d)这个就是断言 就是条件。只是条件不参与匹配
//找\w (英文|数字|下划线) 而且后面跟着\d 数字的。
//所以符合的有 a2的a w4的w; 


负向前瞻 例子:
'a2*3w4sb'.replace(/\w(?!\d)/g,'X') //输出 aX*XwXX
//主角是\w 只对它进行匹配。
//(?!\d)这个就是断言 就是条件。只是条件不参与匹配
//找\w (英文|数字|下划线) 而且后面不是\d 数字的。
//所以符合的有 2*的2 3w的3 4s的4 sb的s b后面什么都没跟所以符合; 
 


调用方法

RegExp 构造函数

-----Es5时-------
只能new RegExp(字符, 修饰符);
或者new RegExp(/正则/修饰符);
var regex = new RegExp('xyz', 'i');
var regex = new RegExp(/xyz/i);

-----Es6--------
new RegExp(/abc/ig, 'i').flags;
说明:`RegExp`参数1是一个正则对象,可以使用第二个参数指定修饰符。而且,后者修饰符权限更高。
就是 》原有正则对象的修饰符是`ig`,它会被第二个参数`i`覆盖。

风格

Js风格  调用RegExp对象的构造函数
var reg = new RegExp('^[a-z]+[0-9]$', 'gi')

Perl风格 写在斜杠中
var reg = /^[a-z]+[0-9]$/gi

常用方法

  • test 返回布尔值; 注意:慎用正则表达式全局匹配(/g)

    例子:
    /^\d+$/.test('12637') //true
    /^\d+$/.test('sdk')   //false
    
    //全局时
    var regex = /foo/g;
    
    regex.test('foo'); // true; regex.lastIndex等于0 开始查找。
    regex.test('foo'); // false ;基于第一次已经执行regex.lastIndex等于3了。从3开始找找不到 所以返回false
    
  • search 返回搜索到的对应位置 没有则-1

    //注意 search只查找一次,即使设置了g。重复调用也是从起始位置开始

     例子 
     'ad1cd2c'.search(/\d/g) //2  第一个数字的位置  
     'adcd'.search(/\d/g)    //-1 找不到
  • replace 替换

    ('a1b2c3').replace(/\d/g,'数字') //a数字b数字c数字
  • split 分割成数组 里面也能写正则。 如果找不到匹配分割的把自己变数组

     'a12b23c34'.split('1')      //["a", "2b23c34"]
     'a12b23c34'.split(/\d{2}/g) //["a", "b", "c", ""]    
     'a12b23c34'.split(/[23]/g)  //["a1", "b", "", "c", "4"] 
     'a12b23c34'.split(/[55]/g)  //["a12b23c34"]
  • match 与 exec 返回数组 匹配到的字符串

    两者相似又不同。 写法上不一样

    match是字符串方法,写法为:str.match(reg)
    exec是正则表达式方法,写法为:reg.exec(str)

     写法:
     var reg = new RegExp("abc") ; 
     var str = "3abc4,5abc6";
     str.match(reg);
    
     var reg = new RegExp("abc") ; 
     var str = "3abc4,5abc6";
     reg.exec(str ); 
     
     ---------------------------------------
     
     无子表达式非全局时:
     **exec和match执行的结果是一样,均返回第一个匹配的字符串内容;**
     
     var reg = new RegExp("[a-z]+") ; 
     var str = "1abc2,3abc4";
     alert(str.match(reg));
     alert(reg.exec(str));   
     //都是输出  abc
     
     
     无子表达式全局匹配 :
     **match执行了全局匹配查询;exec找到一个匹配即返回。**
     var reg = new RegExp("[a-z]+","g") ; 
     var str = "1abc2,3bcd4";
     console.log(str.match(reg)); //["abc", "bcd"]
     console.log(str.match(reg)); //["abc", "bcd"]
     console.log(reg.exec(str));  //["abc"]
     console.log(reg.exec(str));  //["bcd"]
     //match执行了全局匹配查询;而exec逐次返回。
     
     
     有子表达式 非全局:
     **match exec 都是返回结果 和分组**
     var reg = new RegExp("a(bc)") ; 
     var str = "3abc4,5abc6";
     console.log(str.match(reg)); //["abc", "bc"]
     console.log(reg.exec(str)); //["abc", "bc"]
    
     
     有子表达式 全局:
     **match忽略子表达式,只查找全匹配正则表达式并返回所有内容;
     exec 依然逐次返回结果 分组 
     **
     var reg = new RegExp("a(bc)","g") ; 
     var str = "3abc4,5abc6";
     console.log(str.match(reg));  // ["abc", "abc"]
     console.log(str.match(reg));  // ["abc", "abc"]
     console.log(reg.exec(str));   // ["abc", "bc", index: 1]
     console.log(reg.exec(str));   // ["abc", "bc", index: 7]
    

随手简单正则

/^\d+$/.test('2l')  //只能输入数字

/^\d{n}$/.test('2222')  //只能输入n个数字

/^\d{n,}$/.test('22222')  //只能输入n个以上数字

/^\d{m,n}$/.test('22222')  //只能输入m到n个数字

/^[a-z]+$/i  //只能输入英文

/^[A-Z]+$/.test('SS’)  //只能输入大写英文

/^[0-9a-z]+$/i.test('1223ddsSSk')  //只能输入英文和数字

/^\w+$/.test('wS233_')  //只能英文数字下划线

/^[\u4e00-\u9fa5]+$/.test('大家看') //纯中文

//匹配手机号  : 手机号 1开头 34568 第二位  数字任意9位
/^1[3|4|5|6|8]{1}\d{9}$/.test('13347834892')

//匹配日期格式 YYYY-MM-DD
1/2开头 3个数字 - [0|1][1-9] - [0-1][1-9]
/^[1-9]\d{3}-[0-1]\d-[0-3]\d$/.test('2017-12-20')


//过滤html标签: 以<开头 >结尾的标签  
'幕中闪着凶光。<br/><p/>索拉卡'.replace(/<[^<>]+>/g,'')

//简单版匹配email邮箱:英文数字下划线 @ 英文数字 .com
/^\w+\@[a-z0-9]+(.com)$/.test('@qq.com')

// 网上看到的Email地址:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

clipboard.png

有很多在线正则可视化的网站也是很有意思 写了可以拷贝进去检查看看。

Mart一下 仅供参考 欢迎更正补充 Thanks

阅读 1.5k

喈喱前端笔记
学习的付出 从不欺人

学习的付出 从不欺人。记忆总是苦,写总结最牢固

468 声望
198 粉丝
0 条评论
你知道吗?

学习的付出 从不欺人。记忆总是苦,写总结最牢固

468 声望
198 粉丝
宣传栏