正则表达式简介—描述字符串规则的表达式
正则表达式,全称“Regular Expression”,在代码中常简写为regex、regexp或RE。
正则表达式,就是用某种模式去匹配一类字符串的公式。
JavaScript中正则表达式的定义方法
在JavaScript中,正则表达式是由一个RegExp对象表示的,利用RegExp对象来完成有关正则表达式的操作和功能。
正则表达式的定义共有2种方式:
(1)显式定义;
显式定义必须是使用new关键词来定义。
语法:var 变量名 = new RegExp(pattern,attrs);
(2)隐式定义;
语法:var 变量名 = /pattern/attrs
-pattern:正则表达式规则。
-attrs: 正则表达式属性, 如g代表全局模式,i表示不区分大小写。
举例:1
2var myregex = new ReExp("[0-9]");
var myregex = /[0-9]/;
regexObj.test(str)方法
测试正则表达式与指定字符串是否匹配。
该方法返回一个boolean值。也就是说,test()方法检查字符串str是否符合正则表达式模式regexp,如果符合,则返回true;如果不符合,则返回false。
示例:1
2
3/13566668888/.test(‘1356666888’); // false
/13566668888/.test(‘13566668888’); // true
/13566668888/.test(‘x1356666888y’); // true
锚点—定位符
正则表达式定位符,主要作用是匹配一个位置,包括:
定位符 | 说明 |
---|---|
^ | 限定开始位置的字符 |
$ | 限定结尾位置的字符 |
\b | 限定单词(字)边界的字符 |
\B | 限定非单词(字)边界的字符 |
示例:1
2
3
4
5
6
7
8/^http:/.test('http://www.xifengxx.com') //true
/^http:/.test('ahttp://www.xifengxx.com') //false
/^http:/.test('https://www.xifengxx.com') //false
/\.jpg$/.test('1.jpg') //true
/\.jpg$/.test('1.jpg abc') //false
/\.jpg$/.test('1.png') //false
/\bis\b/.test('this') //false
/\bis\b/.test('that is tom') //true
字符类
此类正则,匹配一类字符串的一个。
字符 | 说明 |
---|---|
[0-9] | 匹配数字,等价于\d |
[a-z] | 匹配英文小写字母 |
[A-Z] | 匹配英文大写字母 |
[0-9a-zA-Z] | 匹配数字或英文字母 |
[^0-9] | 匹配非数字的一个字符 |
示例:1
2
3
4/[0-9]/.test('abc') // false
/[^0-9]/.test('abc') // true
/[a-z]/.test('abc') //true
/./.test('abc') //true
元字符
具有特殊意义的字符
元字符 | 说明 |
---|---|
\d | 匹配数字,相当于[0-9] |
\D | 匹配非数字,相当于[^0-9] |
\w | 匹配包括下划线在内的任意单词字符(包括A-Z,a-z,0-9,_) |
\W | 匹配任意不是字母、数字、汉字或下划线的字符,[^\w] |
\s | 匹配任意的空白符,如空格、换行符、制表符等 |
\S | 匹配任意不是空白符的字符 |
.(点号) | 匹配除了换行符以外的任意字符 |
[…] | 匹配方括号中的所有字符 |
[^…] | 匹配非方括号中的所有字符 |
示例:1
2
3
4/\d/.test('123') //true
/\d/.test('ab23') //true
/\D/.test('123') //false
/\D/.test('123ab') //true
量词—限定符
出现次数
限定符 | 说明 |
---|---|
+ | 重复1次或更多次,+等效于{1,}。 |
* | 重复0次或更多次(任意次数),*等效于{0,} |
? | 重复0次或1次(最多1次),?等效于{0,1}。 |
{n} | 重复n次 |
{n,} | 重复n次或更多次(最少n次) |
{n,m} | 重复n到m次 |
示例:1
2
3/\d*/.test('abc') //true
/https?:/.test('http://www.xifengxx.com') //true
/https?:/.test('httpss://www.xifengxx.com') //false
转义符
如果我们要匹配的字符是元字符,我们就必须在该特殊字符前面加上反斜杠“\”将其进行转义。
例如要匹配字面意义的“\”,就需要使用“\”表示。
需要转义的字符有:$、(、)、*、+、.、[、]、?、\、/、^、{、}、|。
表达式 | 说明 |
---|---|
\r | 回车 |
\n | 换行 |
\ | 匹配“\”本身 |
\^ | 匹配“^” |
\$ | 匹配“$” |
. | 匹配“.” |
示例:1
2/http:\/\//.test('http://www.xifengxx.com') //true
/@163\.com$/.test('abc@163.com') //true
多选分支(|)
当一个字符串的某一子串具有多种可能时,采用分支结构来匹配,“|”表示多个子表达式之间“或”的关系,“|”是以()限定范围的,如果在“|”的左右两侧没有()来限定范围,那么它的作用范围即为“|”左右两侧整体。
表达式 | 说明 | |
---|---|---|
` | ` | 多个子表达式之间取“或”的关系 |
例如,“abc|def1”匹配的是“abc”或“def1”,而不是“abc1”或“def1”。如果要匹配“abc1”或“def1”,应该使用分组符,即“(abc|def)1”。
捕获—捕获组(Capture Group)
保存匹配到的字符串,日后在用。
1.捕获组
捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或手动命名的组里,以供后面引用。
表达式 | 说明 |
---|---|
(Expression) | 普通捕获组,将子表达式Expression匹配的内容保存到以数字编号的组里 |
(? |
命名捕获组,将子表达式Expression匹配的内容保存到以name命名的组里 |
- 普通捕获组(在不产生歧义的情况下,简称捕获组)是以数字进行编号的,编号规则是以“(”从左到右出现的顺序,从1开始进行编号。通常情况下,编号为0的组表示整个表达式匹配的内容。
- 命名捕获组可以通过捕获组名,而不是序号对捕获内容进行引用,提供了更便捷的引用方式,不用关注捕获组的序号,也不用担心表达式部分变更会导致引用错误的捕获组。
示例:/(.+)@(163|126|188)\.com$/ //匹配网易邮箱,捕获。
2. 非捕获组
一些表达式中,不得不使用( ),但又不需要保存( )中子表达式匹配的内容,这时可以用非捕获组来抵消使用( )带来的副作用。
表达式 | 说明 |
---|---|
(?:Expression) | 进行子表达式Expression的匹配,并将匹配内容保存到最终的整个表达式的区配结果中,但Expression匹配的内容不单独保存到一个组内 |
示例:/(.+)@(?:163|126|188)\.com$/ //匹配网易邮箱,但不捕获
3. 反向引用
捕获组匹配的内容,可以在正则表达式的外部程序中进行引用,也可以在表达式中进行引用,表达式中引用的方式就是反向引用。
反向引用通常用来查找重复的子串,或是限定某一子串成对出现。
表达式 | 说明 |
---|---|
\1,\2 | 对序号为1和2的捕获组的反向引用 |
\k |
对命名为name的捕获组的反向引用 |
举例:
“(a|b)\1”在匹配“abaa”时,匹配成功,匹配到的结果是“aa”。
“(a|b)”在尝试匹配时,虽然既可以匹配“a”,也可以匹配“b”,但是在进行反向引用时,对应()中匹配的内容已经是固定的了。1
2
3
4var a='abaa';
a.match(/(a|b)\1/) // ['aa','a']
var a='abaa';
a.match(/(a|b)\1/g) //['aa']
match方法返回一个数组:数组的第一项是与整个模式匹配的字符串,之后的每一项(如果有)保存着与正则表达式中的捕获组匹配的字符串;如果调用的RegExp带有g标识,那么match方法返回一个包含所有匹配的字符串的数组,而没有捕获组字符串。
4. 环视(Look Around)
环视只进行子表达式的匹配,匹配内容不计入最终的匹配结果,是零宽度的。
环视按照方向划分有顺序和逆序两种,按照是否匹配有肯定和否定两种,组合起来就有四种环视。环视相当于对所在位置加了一个附加条件。
表达式 | 说明 |
---|---|
(?<=Expression) |
逆序肯定环视,表示所在位置左侧能够匹配Expression |
(?<!Expression) |
逆序否定环视,表示所在位置左侧不能匹配Expression |
(?=Expression) |
顺序肯定环视,表示所在位置右侧能够匹配Expression |
(?!Expression) |
顺序否定环视,表示所在位置右侧不能匹配Expression |
举例:
- “(?<=Windows )\d+”在匹配“Windows 2003”时,匹配成功,匹配结果为“2003”。我们知道“\d+”表示匹配一个以上的数字,而“(?<=Windows )”相当于一个附加条件,表示所在位置左侧必须为“Windows ”,它所匹配的内容并不计入匹配结果。
- 同样的正则在匹配“Office 2003”时,匹配失败,因为这里任意一串数字子串的左侧都不是“Windows ”。
- “(?!1)\d+”在匹配“123”时,匹配成功,匹配的结果为“23”。“\d+”匹配一个以上数字,但是附加条件“(?!1)”要求所在位置右侧不能是“1”,所以匹配成功的位置是“2”前面的位置。
1
2
3
4
5
6
7
8
9/(?!1)\d+/.test('123') //true
'123'.match(/(?!1)\d+/) //['23']
/(?=1)\d+/.test('123') //true
'123'.match(/(?=1)\d+/) //['123']
/(?!1)\d+/.test('1231') //true
'1234'.match(/(?!1)\d+/) //['234']
'1234'.match(/(?=1)\d+/) //['1234']
对以上内容的理解:/(?!1)\d+/.test('123')
有4个位置,/(?!1)\d+/表示所在位置右侧不能匹配到1,而位置0右侧匹配1,位置1右侧开始就不匹配1,所以,可以匹配到,最终匹配的结果为’23’.
正则表达式匹配的贪婪与非贪婪模式
1. 什么是正则表达式的贪婪与非贪婪匹配
如:String str=”abcaxc”;
Patter p=”ab*c”;
- 贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(ab*c)。
- 非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(ab*c)。
2. 编程中如何区分两种模式
默认是贪婪模式;在量词后面直接加上一个问号?就是非贪婪模式。
量词:{m,n}:m到n个
*:任意多个
+:一个到多个
?:0或一个
3. 正则表达式量词分别是:贪婪的、惰性的、支配性的。
贪婪:? + {n} {n,m} {n,}
惰性:?? ? +? {n}? {n,m}? {n,}?
支配:?+ *+ ++ {n}+ {n,m}+ {n,}+
分别的意思是:
零次或一次出现、零次或多次出现、一次或多次出现、恰好N次出现、至少N次最多M次出现、至少N次出现。
- 贪婪量词:先看整个字符串是否匹配,如果不匹配就把最后一个字符去掉在进行匹配,不匹配继续去掉最后一个字符,指导找到一个匹配或者不剩任何字符才停止。
- 惰性量词:先看第一个字符串是否匹配,如果第一个不匹配就在加入第二个字符串依此类推,指导找到一个匹配或者不剩任何字符才停止,贪婪量词与贪婪量词的方法正好相反.
- 浏览器对量词的支持还不完善,IE和OPERA都不支持量词,MOZILLA把支配量词看作是贪婪的例子:
1
2
3var str = 'aabbazbbwwbbaa';
var arr =str.match(/.*bb/); //aabbazbbwwbb,贪婪的
var arr =str.match(/.*?bb/g); //aabb azbb wwbb 返回一个数组包含3个值,惰性的
str.match(regexp)
捕获匹配字符串1
2
3
4
5
6
7
8var url = 'http://blog.163.com/album?id=1#comment';
var reg = /(https?:)\/\/([^\/]+)(\/[^\?]*)?(\?[^#]*)?(#.*)?/;
var arr = url.match(reg);
var protocol = arr[1];
var host = arr[2];
var pathname = arr[3];
var search = arr[4];
var hash = arr[5];
str.replace(regexp/substr,replacement)
替换一个子串1
2
3var str = 'The price of tomato is 5, the price of apple is 10.';
var c=str.replace(/(\d+)/g,'$1.00');
console.log(c); //The price of tomato is 5.00, the price of apple is 10.00.
regexpObj.exec(str)
更强大的检索
-更详尽的结果:index
-过程的状态:lastIndex1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var reg = /(.)(\d+)/g;
var scores = 'Tom $88, Nicholas ¥100, jack ¥38.';
var result;
while(result = reg.exec(scores)){
console.log(result);
console.log(reg.lastIndex);
}
/*
上述结果为:
["$88", "$", "88", index: 4, input: "Tom $88, Nicholas ¥100, jack ¥38."]
7
["¥100", "¥", "100", index: 18, input: "Tom $88, Nicholas ¥100, jack ¥38."]
22
["¥38", "¥", "38", index: 29, input: "Tom $88, Nicholas ¥100, jack ¥38."]
32
*/
正则表达式优先级
在正则表达式中,同样存在优先级顺序。正则表达式存在元字符、限定符、转义字符、|等运算符。在匹配过程中,正则表达式都是先规定了这些运算或表达式的优先级。
正则表达式也可以像数学表达式一样来求值。也就是说,正则表达式可以从左到右,并按照一个给定的优先级来求值。
运算符或表达式 | 说明 | |
---|---|---|
\ | 转义符 | |
()、(?:)、(?=)、[] | 圆括号或方括号 | |
*、+、?、{n}、{n,}、{n,m} | 限定符 | |
^、$、\b、\B | 位置和顺序 | |
` | ` | 选择符,“或”运算 |
上面优先级是从高到低排列。