为了账号安全,请及时绑定邮箱和手机立即绑定

依据Samaritan89的正则课程做的javascript正则笔记

标签:
JavaScript

JS中有两种方式创建正则对象:
1、字面量:var reg = /\bis\b/g; //g表示全局匹配。不加表示搜索到第一个停止。
2、构造函数 var reg= new RegExp('\\bis\\b', 'g');(注意有两个反斜线转义)

(另外使用正则表达式字面量和使用RegExp构造函数创建的正则表达式不一样。在ECMAScript 3 中,正则表达式字面量始终会共享同一个RegExp 实例,而使用构造函数创建的每一个新RegExp 实例都是一个新实例。ECMAScript 5 明确规定,使用正则表达式字面量必须像直接调用RegExp 构造函数一样,每次都创建新的RegExp实例。IE9+、Firefox 4+和Chrome 都据此做出了修改。)

正则表达式由两种基本字符类型组成:
(1)原意文本(比如abc表示匹配abc)
(2)元字符->在正则表达式中有特殊含义的非字母字符(比如\b表示单词边界,并不代表匹配反斜杠和字母b)

这些都是元字符:* + ? $ ^ . | \ ( ) [ ] { }

[]表示匹配括号中的一类字符:如表达式[abc]表示把字符a或b或c归为一类,可以匹配到这类字符。如图

例子:

'a1b2c3d4e5'.replace(/[abc]/g,'X')=》"X1X2X3d4e5"

使用^创建反向类。如[^abc]表示不是字符a或b或c的内容。如图:

例子:
'a1b2c3d4e5'.replace(/[^abc]/g,'X')=》"aXbXcXXXXX"

我们可以使用[a-z]来连接两个字符表示从a到z的任意字符。这是个闭区间意味着包括a和z,[]中也可以连写,如[a-zA-Z]表示匹配所有大小写字母

==================
预定义类:

字符等价类含义./^\r\n/除换行回车外的任意字符\d[0-9]任意数字字符\D[^0-9]非数字字符\s[\r\n\t\x0B\f]空白符\S[^\r\n\t\x0B\f]非空白符\w[a-zA-Z_0-9]单词字符(字母数字下划线共63个字符)\W[^a-zA-Z_0-9]非单词字符

===================
边界类:
^开始 (注意在中括号内是取反)
$ 结束
\b 单词边界 \B 非单词边界

===================
修饰符:
g: global 全局搜索,默认是false
i:ignore case 忽略大小写,默认大小写敏感
m:multiline 多行搜索。默认是false。
multiple的例子:

var aaa='@123\n@234\n@345';

aaa.replace(/^@\d/gm,'Q')如果不加m则只有"@1"会被替换

=======================
量词(即表示数量的词):
字符含义?出现0次或1次(至多出现一次)+出现一次或多次(至少出现一次)*出现0次或多次(任意次){n}出现n次{n,m}出现n-m次{n,}至少出现n次

=======================
贪婪模式与非贪婪模式:
默认是尽可能多的匹配(贪婪模式)如:'12345678'.replace(/\d{3,6}/g, 'X');=>"X78"(匹配到12345了)
让正则表达式尽可能少的匹配,也就是说一旦匹配成功就不再继续尝试匹配(非贪婪模式),启用非贪婪模式很简单,只需要在量词后面加上?就可以了.
如:'123456780'.match(/\d{3,5}?/g)=>["123", "456", "789"]
或者'12345678'.replace(/\d{3,6}?/g, 'X');=>"XX78"(匹配到123和456了)

================
分组:
使用( )可以达到分组的功能,使量词作用于分组或:使用 | 可以达到或的效果。
或的例子:'jia5832960asfa'.replace(/jia58|3296/g,'X');=>'XX0asfa',会匹配jia58或3296
反向引用
$捕获的是分组的内容,没有分组$就没有意义。
例如:想要将2015-11-23替换为23/11/2015,如下,
'2015-11-23'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$3/$2/$1')=》"23/11/2015"

===========
忽略捕获分组,只需要在分组内加上?:(问号冒号)就可以了。
'2016-11-23'.replace(/(?:\d{4})-(\d{2})-(\d{2})/g, '$3/$2/$1')=》"$3/23/11"
上面第一个分组就忽略掉了,所以此时$1就是11$,$2是23了。

===========
前瞻
名次解释:正则表达式从文本头部向尾部开始解析,文本尾部方向称作“前”,前瞻就是指正则表达式匹配到规则的时候,向前检查是否符合断言,后顾/后瞻方向相反。
名称正则含义正向前瞻exp(?=assert)匹配exp正则且满足assert条件的负向前瞻exp(?!assert)匹配exp正则且不满足assert条件的正向后顾exp(?<=assert)javascript不支持负向后顾exp(?<!assert)javascript不支持
注:以上assert断言部分也是正则表达式。
例子:
'a2*34*()va23'.replace(/\w(?=\d)/g,'X')=》"X2*X4*()vXX3"(正向前瞻)
匹配单词并且后面是数字的。
'a2*34*()va23'.replace(/\w(?!\d)/g,'X')=》"aX*3X*()Xa2X"(反向前瞻)
匹配单词并且后面不是数字的。
============JS中正则表达式的相关内容
正则对象的几个属性(都是只读的)
global 是否全局搜索,默认false
ignoreCase 是否忽略大小写,默认false
multiline 是否多行搜索,默认false
lastIndex 当前表达式匹配内容的最后一个字符的下一个位置(看下面例子)
source 正则表达式的文本字符串

例子:
var reg1 = /\d/, reg2 = /\d/gim; reg1.multiline =》false reg2.ignoreCase =》true reg1.global =》false reg2.global =》true

=================
RegExp构造函数原型上的两个方法:
RegExp.prototype.test(str)
很简单,即检测传入的字符串是否和正则表达式相匹配。
例子:
var reg1 = /\d/, reg2 = /\d/gim;
reg2.test('1') =》true,此时reg2.lastIndex值为1
reg2.test('1') =》false,此时reg2.lastIndex值为2 //执行第二次的时候为false了。因为lastIndex的值改变了。
一般用test方法只是检测是否有匹配,所以不建议加g.
RegExp.prototype.exec(str)
如果没有匹配到文本返回null,有匹配到返回一个结果数组:
-index 声明匹配文本的第一个字符的位置;
-input 存放被检索的字符串 string
非全局调用exec()时(即没有g修饰符时),返回的数组:
第一项是与正则表达式相匹配的文本;第二个元素是与RegExp对象的第一个子表达式(分组)相匹配的文本(如果有的话);第三个元素是与RegExp对象的第二个子表达式相匹配的文本(如果有的话)以此类推...
还是看例子吧:
var reg1 = /\d(\w)\d/; var reg2= /\d(\w)\d/g; //全局搜索 var str = '$2b3asd4u8989sjf8b4'; var result1 = reg1.exec(str); var ret; console.log(result1); =》 [ '2b3', 'b', index: 1, input: '$2b3asd4u8989sjf8b4' ] console.log(result1.toString()); =》 2b3,b while(ret = reg2.exec(str)) { console.log(ret.index+ '\t' + ret.toString()); }
结果:
1 2b3,b
7 4u8,u
10 989,8
16 8b4,b

=================String对象上的几个原型方法
String.prototype.search(regexp)(注意该方法是强制正则匹配模式,意即传入的参数如果不是正则会将其new RegExp(str)转为正则对象)
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,该方法只返回第一个匹配结果的index,查找不到返回-1。
search方法不执行全局匹配,它将忽略标志g,并且总是从字符串的开始进行检索。
但String.prototype.indexOf(str)则只是按字符串匹配。
看例子:
var str = "123456789.abcde"; // 比刚才多了一个.而已 console.log( str.search(".") ); // 0 因为正则 . 匹配除\n以外任意字符 console.log( str.indexOf(".") ); // 9 只能匹配字符 . console.log( str.search("\\.") ); // 9 相当于 new RegExp("\\.") console.log( str.indexOf("\\.") ); // -1 匹配字符 \. 所以不存在 console.log( str.search(/\./) ); // 9 正则匹配转以后的 . 字符 console.log( str.indexOf(/\./) ); // -1 相当于匹配字符串 "/\./" 所以不存在


String.prototype.match(regexp)
非全局匹配该方法只执行一次匹配,没有匹配到返回null,若有匹配返回一个匹配文本相关的数组。
除了常规的数组元素外返回的数组还有两个对象属性index和input。解释与exec完全一样。只不过是调用方式不一样。上面的是正则对象调用exec方法字符串作为参数,现在是字符串调用match方法正则对象作为参数。

全局匹配(带有修饰符g)该方法将执行全局检索,如果有找到返回null,若有匹配则返回一个数组,数组中存放的只有匹配的结果,没有index和input属性,也没有分组信息了!
看例子吧:
var reg = /\d(\w)\d/g; var str = '$2b3asd4u8989sjf8b4'; var ret1; while (ret1 = reg.exec(str)) { console.log(ret1); } console.log(str.match(reg));=》 [ '2b3', 'b', index: 1, input: '$2b3asd4u8989sjf8b4' ] [ '4u8', 'u', index: 7, input: '$2b3asd4u8989sjf8b4' ] [ '989', '8', index: 10, input: '$2b3asd4u8989sjf8b4' ] [ '8b4', 'b', index: 16, input: '$2b3asd4u8989sjf8b4' ] //以上是exec方法执行的结果 [ '2b3', '4u8', '989', '8b4' ] //match少了input和index属性以及分组信息


String.prototype.split([separator[, limit]])
The separator is treated as a string or a regular expression.


String.protoype.replace(regexp|substr, newSubStr|function)
一般来说,function有三个参数(如有分组则可能有3+分组数个参数),分别是匹配到的字符串、分组内容(若无分组则没有该参数)、index、input(原字符串)。
例子:
var str = 'a1b2c3d4e5f6'; var newStr = str.replace(/(\d)(\w)(\d)/g, function(match,group1,group2,group3,index,input){ //这里有3个分组 console.log(match); return group1+group3; }); console.log(newStr);
1b2
3d4
5f6
a12c34e56
====================总结性===================
综上所学知识可以解决一个面试中经常会被问及的问题了:
function getQueryObject(url) { url = url == null ? window.location.href : url; var search = url.substring(url.lastIndexOf("?") + 1); var obj = {}; var reg = /([^?&=]+)=([^?&=]*)/g; search.replace(reg, function (rs, $1, $2) { var name = decodeURIComponent($1); var val = String(decodeURIComponent($2)); obj[name] = val; return rs; }); return obj; }
附:在线查看正则表达式规则 正则学习网站
如上字符串对象共有4个方法,可以使用正则表达式:match()、replace()、search()和split()。
ES6将这4个方法,在语言内部全部调用RegExp的实例方法,从而做到所有与正则相关的方法,全都定义在RegExp对象上。
String.prototype.match 调用 RegExp.prototype[Symbol.match]
String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
String.prototype.search 调用 RegExp.prototype[Symbol.search]
String.prototype.split 调用 RegExp.prototype[Symbol.split]

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消