正则表达式入门教程

正则表达式简介—描述字符串规则的表达式

正则表达式,全称“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
2
var 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) 命名捕获组,将子表达式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
4
var 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
    3
    var str = 'aabbazbbwwbbaa';
    var arr =str.match(/.*bb/); //aabbazbbwwbb,贪婪的
    var arr =str.match(/.*?bb/g); //aabb azbb wwbb 返回一个数组包含3个值,惰性的

str.match(regexp)

捕获匹配字符串
正则表达式1

1
2
3
4
5
6
7
8
var 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
3
var 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
-过程的状态:lastIndex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var 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 位置和顺序
` ` 选择符,“或”运算

上面优先级是从高到低排列。

参考资源:

  1. http://blog.csdn.net/lxcnn/article/details/4268033 [☆☆☆☆☆推荐]
  2. http://deerchao.net/tutorials/regex/regex.htm [☆☆☆☆推荐]
  3. http://www.365mini.com/page/19.htm [☆☆☆推荐]
坚持原创技术分享,您的支持将鼓励我继续创作!