正则表达式,也称划定规矩表达式,经常运用其来完成对字符串的校验和过滤。由于正则表达式的灵活性、逻辑性和功能性都异常壮大,而且 能够运用很简朴的体式格局完成对庞杂字符串的掌握,所以许多程序言语都支撑正则表达式。在JavaScript
中正则示意也异常壮大和有用。
基本情势
正则表达式(regular expression)是一种表达文本情势(即字符串组织)的要领,有点像字符串的模板,经经常使用作根据“给定情势”婚配文本的东西。比方,正则表达式给出一个Email地点的情势,然后用它来肯定一个字符串是不是为Email地点。JavaScript的正则表达式系统是参照Perl 5竖立的。
新建正则表达式有两种要领。一种是运用字面量,以斜杠示意最先和完毕。
// 字面量情势
var telRegex1 = /^1[3|5|7|8]\d{9}$/;
// 组织函数情势
var telRegex2 = new RegExp('^1[3|5|7|8]\\d{9}$');
以上都是建立了一个内容为^1[3|5|7|8]\d{9}$
的正则表达式,其示意对一个手机号码的校验。必需以1最先,第二位为3/5/7/8,以后为9位数字。
这两种写法——字面量和组织函数——在运行时有一个纤细的区分。采纳字面量的写法,正则对象在代码载入时(即编译时)天生;采纳组织函数的要领,正则对象在代码运行时天生。考虑到誊写的方便和直观,现实运用中,基本上都采纳字面量的写法。
有一点须要注重,运用组织函数建立正则表达式时,传入的参数是字符串情势的,在字符串内部,\
本身也是一个转义符,因而须要再运用一个\
来对其举行正则表达式的转义。上面第二个示例中,\\d
才代表恣意数字。
关于正则表达式中,种种标记的寄义,以及运用要领,请看背面的引见:
元字符
一些经常使用的元字符以下:
.
婚配除换行符以外的恣意字符\w
婚配字母或数字或下划线或汉字\s
婚配恣意的空白符\d
婚配数字\b
婚配单词的最先或完毕^
婚配字符串的最先处$
婚配字符串的完毕处。*
婚配前面的子表达式恣意次。?
婚配前面子表达式0次或一次,等价于{0, 1}
。+
婚配之前子表达式一次到屡次,等价于{1, }
。{n}
婚配之前的子表达式n次。{m,n}
婚配之前的子表达式起码m次,最多n次。{n, }
婚配之前的子表达式最少n次。[xyz]
字符鸠合,示意个中恣意一个字符。示意局限可用-
链接,比方[a-z]
示意a-z之间的恣意一个字母。还能够如许誊写[A-Za-z0-9]
。[^xyz]
字符即可,示意非个中恣意一个字符。示意局限可用-
链接,比方[^a-z]
示意非 a-z之间的恣意一个字母。|
示意或(or)
关联,比方com|cn
,示意婚配com或许cn。()
用于分组,其分组中的内容可已由过程$1-$9
按递次猎取(字符串相干要领中),以后的正则中也能够经由过程\1-\9
举行援用(正则表达式内部)。(分组0示意悉数正则婚配内容或悉数正则表达式)
在正则表达式中,以上这些以及一些未列出的元字符都是有本身寄义的,假如我们须要婚配这些元字符本身,能够运用
\
对其举行转义即可。
更多元字符能够检察:正则表达式
属性
修饰符
ignoreCase
:返回一个布尔值,示意是不是设置了i修饰符,该属性只读。global
:返回一个布尔值,示意是不是设置了g修饰符,该属性只读。multiline
:返回一个布尔值,示意是不是设置了m修饰符,该属性只读。sticky
:ES6返回一个布尔值,示意是不是设置了y修饰符,只读。
var r = /abc/igm;
r.ignoreCase; // true
r.global; // true
r.multiline; // true
婚配时属性
lastIndex
:返回下一次最先搜刮的位置。该属性可读写,然则只在设置了g修饰符时有意义。source
:ES5返回正则表达式的字符串情势(不包含反斜杠),该属性只读。flags
:ES6返回正则表达式中的修饰符。
var r = /abc/igm;
r.lastIndex; // 0
r.source; // "abc"
r.flags; //"igm"
要领
test()
正则对象的test
对象吸收一个字符串,示意测试字符串,返回一个布尔值,示意是此字符串是不是满足婚配前提。
telRegex1.test('13612341234'); // true
telRegex2.test('13612341234'); // true
telRegex1.test('136123412'); // false
假如正则表达式带有g
修饰符,则每一次test
要领都从上一次完毕的位置最先向后婚配。同时,能够经由过程正则对象的lastIndex
属性指定最先搜刮的位置。
var xReg = /x/g;
var str = 'xyz_x1_y1_x3';
xReg.lastIndex; // 0
xReg.test(str); // true
xReg.lastIndex; // 1
xReg.test(str); // true
xReg.lastIndex; // 5
// 指定位置最先 指定下次婚配从末了一名最先,就婚配不到了
xReg.lastIndex = 11; // 11
xReg.test(str); // false
xReg.lastIndex; // 0
var indexReg = /^(?:http|https).+\/jwebui\/pages\/themes\/(\w+)\/\1\.jspx(\?\S+)?$/i ;
上面是一个F8中搜检是不是为首页的正则表达式。
最最先的
^
和末了的$
离别示意婚配的最先和完毕。(?:http|https)
示意二者之一,这么写黑白猎取的组婚配,()
不会被分组存储。也能够写成(http|https)
然则背面的\1
就须要替代成\2
了,由于这么写时此处形成了第一个分组。.+
就是恣意字符最少涌现一次。\/jwebui\/pages\/themes\/
就是婚配字符串"/jwebui/pages/themes/"
。(\w+)
作为第一个分组,示意恣意字母或数字或下划线或汉字最少涌现一次。\1
示意对第一个分组的援用,再反复第一分组的内容 。\.jspx
示意.jspx
。(\?\S+)?
示意(\?\S+)
婚配的内容涌现0次或一次。个中:\?
示意?
。\S+
示意恣意可见字符涌现最少一次。
`
exec()
正则对象的exec
要领,能够返回婚配效果。假如发明婚配,就返回一个数组,成员是每个婚配胜利的子字符串,不然返回null
。
假如正则示意式包含圆括号(即含有“组婚配”),则返回的数组会包含多个成员。第一个成员是悉数婚配胜利的效果,背面的成员就是圆括号对应的婚配胜利的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。悉数数组的length
属性即是组婚配的数目再加1。
var ipReg = /(\d{1,3}\.){3}(\d{1,3})/;
var ipStr = 'My ip is "192.168.118.47" , please tell me yours';
ipReg.exec(ipStr); // ["192.168.118.47", "118.", "47"]
上面第一段代码示意一个简朴的IP磨练,数字的1-3位以后紧跟一个.
,接着这个团体要涌现3次,末了再有一段数字的1-3位。效果数组中,第一个值示意婚配到的效果,以后的示意正则分组婚配到的内容。
假如正则表达式加上g修饰符,则能够运用屡次exec要领,下一次搜刮的位置从上一次婚配胜利完毕的位置最先。同时还能够指定lastIndex
,使之下次从指定位置最先(可见之前的test
示例)。
var ipLastReg = /\d+(?=;)/g;
var ipsStr = '192.168.118.47;192.168.118.46;192.168.118.48;';
ipLastReg.exec(ipsStr); // ["47"]
ipLastReg.exec(ipsStr); // ["46"]
ipLastReg.exec(ipsStr); // ["48"]
上面代码中正则中的(?=;)
示意先行断言,示意只婚配在;
前面\d+
。
假如只是为了获得是不是婚配,请运用
RegExp.test()
要领或字符串实例的.search()
替代,效力更高。
字符串相干要领
之所以称之为字符串相干要领是由于其是在字符串上挪用的(虽然ES6最先,内部挪用的是正则上的要领,但照样在字符串上供应的进口)。
match()
:返回一个数组,成员是一切婚配的子字符串。search()
:根据给定的正则表达式举行搜刮,返回一个整数,示意婚配最先的位置。replace()
:根据给定的正则表达式举行替代,返回替代后的字符串。split()
:根据给定划定规矩举行字符串支解,返回一个数组,包含支解后的各个成员。
match()
match
要领对字符串举行正则婚配,返回婚配效果。此要领要领与正则对象的exec
要领异常相似:婚配胜利返回一个数组,婚配失利返回null
。假如正则表达式带有g
修饰符,则该要领与正则对象的exec
要领行动差别,会一次性返回一切婚配胜利的效果。
var ipLastReg = /\d+(?=;)/g;
var ipsStr = '192.168.118.47;192.168.118.46;192.168.118.48;';
ipsStr.match(ipLastReg); // ["47", "46", "48"]
上面的正则是婚配IP中的末了一名,个中运用了(?=;)
意为先行断言,示意只婚配在;
之前的内容,然则不包含;
。关于更多先行断言,请看下文。
search()
search
要领,返回第一个满足前提的婚配效果(可直接运用字符串,不一定是正则对象)在悉数字符串中的位置。假如没有任何婚配,则返回-1
。
var nowDateStr = '2016-11-1';
var testReg = /-/g;
nowDateStr.search(testReg); // 4
// 再次查找照样4
nowDateStr.search(testReg); // 4
// 搜检lastIndex 并设置
testReg.lastIndex; // 0
testReg.lastIndex = 6;
nowDateStr.search(testReg); // 4 效果仍为4
search
要领老是从字符串的最先位置查找,与正则表达式的g
修饰符和lastIndex
属性无关。
replace()
replace
要领能够替代婚配的值,返回替代后的新字符串。它接收两个参数,第一个是搜刮情势(可直接运用字符串,不一定是正则对象),第二个是替代的内容(可运用字符串或一个函数)。搜刮情势假如不加g修饰符,就替代第一个婚配胜利的值,不然替代一切婚配胜利的值。
个中replace
要领的第二个参数能够运用美圆标记$,用来指代所替代的内容,详细以下所示:
$&
指代婚配的子字符串。$`
指代婚配效果前面的文本。$'
指代婚配效果背面的文本。$n
指代婚配胜利的第n组内容,n是从1最先的自然数。$$
指代美圆标记$。
var re = /-/g;
var str = '2016-11-01';
var newstr = str.replace(re,'.');
console.log(newstr); // "2016.11.01"
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1');
// "world hello"
'abc'.replace('b', '[$`-$&-$\']');
// "a[a-b-c]c"
第二个参数为函数:
function toCamelStyle(str) {
// 婚配-以及以后的一个字符,个中这个字符在一个分组内
var camelRegExp = /-([a-z])/ig;
return str.replace(camelRegExp, function(all, letter) {
// all为婚配到的内容,letter为组婚配
return letter.toUpperCase();
});
}
toCamelStyle('margin-left'); // "marginLeft"
toCamelStyle('aa-bb-cccc'); // "aaBbCccc"
以上代码展现经由过程正则将aa-bb-cccc
如许的字符串转化为aaBbCccc
这类情势。replace
回调函数吸收两个参数,第一个为婚配到的内容,第二个为婚配到的分组,有若干组就能够传若干个参数,在此以后还能够有两个参数,一个为婚配到内容在原字符串的位置,另一个是原字符串。
split()
split
要领根据正则划定规矩支解字符串,返回一个由支解后的各个部份构成的数组。该要领接收两个参数,第一个参数是分开划定规矩(可直接运用字符串,不一定是正则对象),第二个参数是返回数组的最大成员数。
'2016-11-01'.split('-'); // ["2016", "11", "01"]
'2016-11-01'.split(/-/); // ["2016", "11", "01"]
贪欲情势和懒散情势
当正则表达式中包含能接收反复的限定符时,一般的行动是(在使悉数表达式能获得婚配的前提下)婚配尽量多的字符,称之为贪欲情势。
比方:
var s = 'aaa';
s.match(/a+/); // ["aaa"]
偶然,我们更须要懒散婚配,也就是婚配尽量少的字符。前面给出的限定符都能够被转化为懒散婚配情势,只需在它背面加上一个问号?。如许.*?就意味着婚配恣意数目的反复,然则在能使悉数婚配胜利的前提下运用起码的反复。
var s = 'aaa';
s.match(/a+?/); // ["a"]
以下是一些申明
*?
反复恣意次,但尽量少反复+?
反复1次或更屡次,但尽量少反复??
反复0次或1次,但尽量少反复{n,m}?
反复n到m次,但尽量少反复{n,}?
反复n次以上,但尽量少反复
也就是说默许状况下,都是贪欲情势,加上一个?
时就转化为了懒散情势,也称非贪欲情势。
组婚配
一般一个()
中的内容就构成了一个分组,此分组内容将被存储,可在以后的正则表达式(运用\1-\9
)和相干要领中(运用 $1-$9
)援用,前面已引见过了,就不再说了。
关于组婚配,另有以下几种状况:
非捕捉组
(?:x)
称为非捕捉组(Non-capturing group),示意不返回该组婚配的内容,即婚配的效果中不计入这个括号。
// 一般婚配
var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
url.exec('http://google.com/');
// ["http://google.com/", "http", "google.com", "/"]
// 非捕捉组婚配
var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;
url.exec('http://google.com/');
// ["http://google.com/", "google.com", "/"]
以后先行断言和先行否认断言也都黑白捕捉组
先行断言
x(?=y)
称为先行断言(Positive look-ahead),x
只需在y
前面才婚配,y
不会被计入返回效果。
比方之前婚配ip的例子:
var ipLastReg = /\d+(?=;)/g;
var ipsStr = '192.168.118.47;192.168.118.46;192.168.118.48;';
ipsStr.match(ipLastReg); // ["47", "46", "48"]
上面正则对象中(?=;)
就示意只婚配在;
之前的内容,然则不包含;
。
先行否认断言
x(?!y)
称为先行否认断言(Negative look-ahead),x
只需不在y
前面才婚配,y
不会被计入返回效果。
var xreg = /\d+(?!%)/g ;
xreg.exec('100% is 1'); // ["10"]
xreg.exec('100% is 1'); // ["1"]
/\d+?(?!%)/.exec('100% is 1'); // ["1"]
上面代码示意婚配不在%
前的数字,xreg
中直接誊写的\d+
示意贪欲情势,因而第一次婚配到的是10,第二次才会婚配到背面的1,由于作为数字10本身也不在%
前面,正则不会将100当做一个团体(注重:这里须要定义一个正则对象来挪用,直接以字面量情势的正则挪用时,每次挪用都是一个新对象,效果始终是10
)。
为了一次婚配到末了的1
,我们在\d+
以后加一个?
将其转为非贪欲情势即可。
为了一次婚配到前面100
中的1
,我们在\d+
以后加一个?
将其转为非贪欲情势即可。
ES6之前,
JavaScript
中不支撑后行断言和否认后行断言,ES6中添加了对此的支撑,请看以后的ES扩大部份。
ES6扩大
组织函数
RegExp组织函数的参数有两种状况。
第一种状况是,参数是字符串,这时候第二个参数示意正则表达式的修饰符(flag)。
第二种状况是,参数是一个正则示意式,此时不能有第二个参数,会返回一个原有正则表达式的拷贝。
ES6 针对第二种状况,许可传入第二个参数,用于设置第一个参数正则表达式的修饰符。
var regex = new RegExp(/xyz/, 'i'); // ES6之前 语法毛病
new RegExp(/abc/ig, 'i'); // ES6中效果为: /abc/i
字符串的正则要领
字符串对象共有4个要领,能够运用正则表达式:match()
、replace()
、search()
和split()
。
ES6将这4个要领,在言语内部悉数挪用RegExp
的实例要领,从而做到一切与正则相干的要领,全都定义在RegExp对象上。
修饰符
ES6对正则表达式添加了u
修饰符,寄义为“Unicode
情势”,用来准确处理大于uFFFF的Unicode字符。也就是说,会准确处理四个字节的UTF-16编码。
ES6还为正则表达式添加了y
修饰符,叫做“粘连”(sticky
)修饰符。
y
修饰符的作用与g
修饰符相似,也是全局婚配,后一次婚配都从上一次婚配胜利的下一个位置最先。差别之处在于,g
修饰符只需盈余位置中存在婚配便可,而y修饰符确保婚配必需从盈余的第一个位置最先,这也就是“粘连”的涵义。
var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;
// 第一次都能准确婚配
r1.exec(s); // ["aaa"]
r2.exec(s); // ["aaa"]
// 第二次效果就不一致了
r1.exec(s); // ["aa"]
r2.exec(s); // null
个人明白,\y
是相似于在每次婚配时隐式地添加了^
,示意最先位置。
属性
ES5中,正则对象存在source
属性,用于返回正则表达式本身。
ES6中,又添加了flags
属性,用于返回正则对象的一切修饰符。
后行断言
后行断言于先行断言相反。比方/(?<=y)x/
示意婚配x
,然则请求x
必需在y
背面。
同理 后行否认断言则为:/(?<!=y)x/
示意婚配x
,然则请求x
不能在y
背面。
须要注重的是,存在后行断言时,正则实行递次发生了转变,会先婚配后行断言的这部份,再婚配其他的的,递次变成了从右向左。因而一些婚配操纵的效果能够大不一致,而且正则中的
\1-\9
的援用递次也会发生变化。
参考链接
原文宣布在我的博客JavaScript正则表达式RegExp,迎接接见!
毛病修改
先行否认断言中
为了一次婚配到末了的1
,我们在\d+
以后加一个?
将其转为非贪欲情势即可。
为了一次婚配到前面100
中的1
,我们在\d+
以后加一个?
将其转为非贪欲情势即可。