正则表达式是指按照某种规则去匹配符合条件的字符串。
语法
JS通过内置对象RegExp支持正则表达式。有两种方法实例化RegExp对象--字面量与构造函数。
字面量
语法:/正则表达式主题/修饰符(可选)
示例:
1 var reg = /\bis\b/g;
2 var str = 'He is a boy.This is a boy.';
3 console.log(str.replace(reg, 'IS')); //'He IS a boy.This IS a boy.'
构造函数
语法:new RegExp('正则表达式主题','修饰符')
示例:
1 var reg = new RegExp('\\bis\\b', 'g'); 2 var str = 'He is a boy.This is a boy.'; 3 console.log(str.replace(reg, 'IS')); //'He IS a boy.This IS a boy.'
修饰符
g : global,全文搜索。默认搜索到第一个匹配停止。
i : ignore case,忽略大小写。默认大小写敏感。
m : multiple lines,多行搜索。
元字符
正则表达式由两种基本字符类型组成:原义文本字符、元字符。
元字符是在正则表达式中有特殊含义的非字母字符。
* + ? $ ^ . | \ () {} []
字符 | 含义 |
\t | 制表符 |
\v | 垂直制表符 |
\n | 换行符 |
\r | 回车符 |
\0 | 空字符 |
\f | 换页符 |
\cX | 与X对应的控制字符(Ctrl + X) |
\a | alert字符 |
\e | escape字符 |
\b | 单词边界 |
字符类
一般情况下正则表达式一个字符对应字符串一个字符
示例:
1 console.log(/ab/.test('abcd')); //true
可以使用元字符[]来构建一个简单的类。所谓类是指符合某些特性的队形,是一个泛指,并不是特指某个字符。例如表达式[abc]把字符a或b或c归为一类,表达式可以匹配这类的字符。
示例:
1 console.log('a1b2c3d4ab1'.replace(/[abc]/g, 'X')); //'X1X2X3d4XX1'
字符类取反
使用元字符^创建反向类、负向类(不属于某类的内容)。例如[^abc]表示不是字符a或b或c的内容
示例:
1 console.log('a1b2c3d4ab1'.replace(/[^abc]/g, 'X')); //'aXbXcXXXabX'
范围类
可以使用[a-z]来连接两个字符表示从a到z的任意字符,包括a和z本身
示例:
1 console.log('a1b2c3d4ab1'.replace(/[a-z]/g, 'X')); //'X1X2X3X4XX1'
在[]组成的类内部是可以连写的,如[a-zA-Z]
示例:
1 console.log('a1b2c3d4ab1FDSAF'.replace(/[a-zA-Z]/g, 'X')); //'X1X2X3X4XX1XXXXX'
特殊情况:匹配范围内的-
1 console.log('2017-11-22'.replace(/[0-9-]/g, 'A')); //'AAAAAAAAAA'
预定义类
字符 | 等价类 | 含义 |
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | [^0-9] | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白符 |
\S | [^\t\n\x0B\f\r] | 非空白符 |
\w | [a-zA-Z_0-9] | 单词字符(字母数字下划线) |
\W | [^a-zA-Z_0-9] | 非单词字符 |
边界
字符 | 含义 |
^ | 以xxx开始 |
$ | 以xxx结束 |
\b | 单词边界 |
\B | 非单词边界 |
示例:
1 console.log('This is a boy'.replace(/is/g, 'A')); //'ThA A a boy' 2 console.log('This is a boy'.replace(/\bis\b/g, 'A')); //'This A a boy' 3 console.log('This is a boy'.replace(/\Bis\b/g, 'A')); //'ThA is a boy'
1 console.log('@123@abc@'.replace(/@/g, 'Q')); //'Q123QabcQ' 2 //替换第一个开头的@ 3 console.log('@123@abc@'.replace(/^@/g, 'Q')); //'Q123@abc@' 4 //替换结尾的@ 5 console.log('@123@abc@'.replace(/@$/g, 'Q')); //'@123@abcQ'
1 var str = '@123\n@456\n@789'; 2 console.log(str.replace(/^@/g, 'A')); //这样做只替换了第一行的@ 3 console.log(str.replace(/^@/gm, 'A')); //这样做会替换所有行首的@
量词
字符 | 含义 |
? | 出现零次或一次(最多出现一次) |
+ | 出现一次或多次(最少出现一次) |
* | 出现零次或多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
贪婪模式
匹配尽可能多的字符
1 var str = '12345678'; 2 console.log(str.replace(/\d{3,6}/, 'S')); //S78 3 //尽可能多地匹配到数字出现的第6次
非贪婪模式
匹配尽可能少的字符。
在量词后加?即可
1 var str = '12345678'; 2 console.log(str.replace(/\d{3,6}?/, 'S')); //S45678 3 //尽可能少地匹配到数字出现的第3次
所有 +? 代表匹配一次
分组
使用()可以达到分组的功能。
1 var str = 'a1b2c3d4'; 2 //匹配3次 一个字母一个数字的形式 3 console.log(str.replace(/[a-z]\d{3}/g, 'X')); //a1b2c3d4 不能匹配到 4 console.log(str.replace(/([a-z]\d){3}/g, 'X')); //Xd4 完美匹配
忽略分组
不希望捕获某些分组,只需在分组内添加?:即可
1 var str = '1017-11-27'; 2 console.log(str.replace(/(?:\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1')); //27/$3/11
或
使用 | 可以达到或的效果。
1 //匹配byron或casper 2 var str1 = 'byroncasper'; 3 console.log(str1.replace(/byron|casper/g, 'X')); //XX 4 5 //匹配byronsper或byrcasper 6 var str2 = 'byronsperfdsbyrcasper'; 7 console.log(str2.replace(/byr(on|ca)sper/g, 'X')); //XfdsX
反向引用
使用$1~$n,得到对应分组中匹配到的字串
1 //将2017-11-27替换成11/27/2017 2 var str = '1017-11-27'; 3 str.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1');
前瞻
在正则表达式匹配到规则的时候向前检查是否符合断言。
后顾/后瞻相反。
JS不支持后顾
1 //将 后面是数字的单词字符替换成'X' 2 var str = 'a2*3'; 3 console.log(str.replace(/\w(?=\d)/g, 'X')); //'X2*3' 4 5 var str = 'a2*34v8'; 6 console.log(str.replace(/\w(?=\d)/g, 'X')); //'X2*X4X8'
1 //将 后面不是数字的单词字符替换成'X' 2 var str = 'a2*3vv4'; 3 console.log(str.replace(/\w(?!\d)/g, 'X')); //'aX*XXvX'
正则表达式的对象属性
global:是否全文搜索,默认为false
ignoreCase:是否大小写敏感,默认为false
multiline:多行搜索,默认为false
lastIndex:当前表达式匹配内容的最后一个字符的下一个位置
source:正则表达式的文本字符串
1 var reg1 = /\w/; 2 console.log(reg1.global); //false 3 console.log(reg1.ignoreCase); //false 4 console.log(reg1.multiline); //false 5 console.log(reg1.source); //'\w' 6 7 var reg2 = /\w/gim; 8 console.log(reg2.global); //true 9 console.log(reg2.ignoreCase); //true 10 console.log(reg2.multiline); //true 11 console.log(reg2.source); //'\w'
上面几个属性为只读属性。
1 reg1.global = true; 2 console.log(reg1.global); //false 3 reg1.source = '\d'; 4 console.log(reg1.source); //'\w'
正则表达式的方法
test
用于测试字符串参数中是否存在匹配正则表达式模式的字符串,如果存在返回true,否则返回false
1 var reg1 = /\w/; 2 console.log(reg1.test('$')); //false 3 console.log(reg1.test('a')); //true 重复执行,结果不会变 4 5 var reg2 = /\w/g; 6 console.log(reg2.test('a')); //true 7 console.log(reg2.test('a')); //false
上述代码中reg2的test结果会交替出现,是因为在加了g修饰符的情况下,lastIndex会起作用。所以用test方法时,最好不要用g修饰符
1 var reg2 = /\w/g; 2 console.log(reg2.test('a')); //true 3 console.log(reg2.lastIndex); //1 4 console.log(reg2.test('a')); //false 5 console.log(reg2.lastIndex); //0
exec
使用正则表达式对字符串执行搜索,并将更新全局RegExp对象的属性(主要是说lastIndex)以反映匹配结果。如果没有匹配的文本返回null,否则返回一个结果数组。
非全局
1 var reg = /\d(\w)\d/; 2 var str = '1a2b3c'; 3 console.log(reg.exec(str)); //["1a2", "a", index: 0, input: "1a2b3c"]
其中index表示匹配文本的第一个字符的位置
input存放被检索的字符串string
第0个元素是与正则表达式相匹配的文本
第1个元素是与正则表达式对象的第一个子表达式相匹配的文本(如果有的话,也就是分组文本)
第2个元素是与正则表达式对象的第二个子表达式相匹配的文本(如果有的话),依次类推
全局
1 var reg = /\d(\w)\d/g; 2 var str = '1a2b3c4d5e'; 3 console.log(reg.exec(str)); //["1a2", "a", index: 0, input: "1a2b3c4d5e"] 4 console.log(reg.exec(str)); //["3c4", "c", index: 4, input: "1a2b3c4d5e"] 5 console.log(reg.exec(str)); //null 6 console.log(reg.exec(str)); //["1a2", "a", index: 0, input: "1a2b3c4d5e"]
与正则表达式相关的字符串对象方法
search
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。方法返回第一个匹配结果的index,查找不到返回-1
search()方法不支持全局匹配,会忽略标志g,并且总是从字符串的开始进行检索。
1 console.log('a2b1c3d1'.search('1')); //3 2 console.log('a2b1c3d1'.search(1)); //3 3 console.log('a2b1c3d1'.search(/1/)); //3 4 console.log('a2b1c3d1'.search(/1/g)); //3 5 console.log('a2b1c3d1'.search(/1/g)); //3
match
在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
如果没有找到任何匹配的子串,则返回null。如果找到了一个或多个匹配子串,则返回一个数组。
非全局匹配
如果正则表达式为非全局匹配,match方法就只能在字符串对象中执行一次匹配。
1 var str = 'a1b2c3d4e5'; 2 var reg = /\d(\w)\d/; 3 console.log(str.match(reg)); //["1b2", "b", index: 1, input: "a1b2c3d4e5"] 4 console.log(reg.exec(str)); //["1b2", "b", index: 1, input: "a1b2c3d4e5"]
非全局匹配时与正则表达式的exec方法返回结果相同
全局匹配
进行全局检索,找到字符串对象中的所有匹配子字符串。数组元素中存放的是字符串对象的所有匹配子串,没有index或input属性。
1 var str = 'a1b2c3d4e5'; 2 var reg = /\d(\w)\d/g; 3 var ret = str.match(reg); 4 console.log(str.match(reg)); //["1b2", "3d4"] 5 console.log(ret.index); //undefined 6 console.log(ret.input);//undefined
split
用于把一个字符串分割成字符串数组。
console.log('a,b,c,d'.split(',')); //["a", "b", "c", "d"]
使用正则表达式的情况:
console.log('a1b2c3d4e5f'.split(/\d/)); //["a", "b", "c", "d", "e", "f"]
replace
语法:
String.prototype.replace(str, replaceStr)
String.prototype.replace(reg, replaceStr)
String.prototype.replace(reg, function)
前面两种语法,之前的例子有涉及到。重点看一下最后一个语法。
不会改变原字符串。返回一个替换后的新字符串。
function会在每次匹配替换的时候调用,有四个参数:
1、匹配到的子字符串
2、正则表达式分组内容,没有分组则没有该参数
3、匹配项在字符串中的index
4、原字符串
1 //将a1b2c3替换为a2b3c4 2 var str = 'a1b2c3'; 3 console.log(str.replace(/\d/g, function (match) { 4 return parseInt(match) + 1; 5 })); //'a2b3c4'
1 //将a1b2c3d4e中的b和d去掉 2 //b和d为两个数字中间的字符 3 console.log('a1b2c3d4e'.replace(/(\d)(\w)(\d)/g, function (match, group1, group2, group3) { 4 return group1 + group3; 5 })); //a12c34e