正则表达式(Regular Expression)是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串
一、JS创建正则表达式
1. 创建方式
- 字面量创建
var reg = /正则表达式主体/修饰符(可选)
- 构造函数创建
var reg = new RegExp('\s', 'ig')
注意:构造函数创建方式第一个参数可以使用变量,因此如果想使用字符串变量来创建正则,只能使用构造函数创建法
2. 修饰符
- g:global,全文搜索,不添加的话搜索到第一个结果停止搜索
- i:ingore case,忽略大小写,默认大小写敏感
- m:multiple lines,多行搜索
var str = "abcggab\nabcpab"; var reg1 = /^abc/g; console.log(str.match(reg1)); //['abc'] var reg2 = /^abc/gm; //使用多行搜索 console.log(str.match(reg2)); //['abc', 'abc']
二、JS正则表达式常用方法
1. 正则对象实例的属性
-
source
:正则表达式的源字符串 -
global
:是否全局搜索,默认是false -
ignoreCase
:是否大小写敏感,默认是false -
multiline
:多行搜索,默认值是false -
lastIndex
:是当前表达式模式首次匹配内容中最后一个字符的下一个位置,每次正则表达式成功匹配时,lastIndex
属性值都会随之改变
2. 正则对象实例的方法
RegExp.prototype.test(str)
测试字符串中是否存在正则表达式模式,如果存在则返回true
,否则返回false
RegExp.prototype.exec(str)
将正则表达式模式在字符串中运行查找,如果exec()
找到了匹配的文本,则返回一个结果数组,否则返回 null
- 非全局匹配的情况
- 多次运行返回同一个值,即字符串中第一个被匹配到的结果
- 返回一个数组,第一个元素是与正则表达式匹配的文本,第二个元素是正则中第一个子表达式匹配的结果(如果有的话),第三个元素是是正则中第一个子表达式匹配的结果(如果有的话),以此类推
var reg = /\d(\D)(\d)/;
var r = reg.exec('a1b2c3');
console.log(r); // ["1b2", "b", "2"]
r=reg.exec('a1b2c3');
console.log(r); // ["1b2", "b", "2"]
- 全局匹配的情况
- 当正则对象为全局匹配,执行
exec()
方法时,它会在RegExp实例的lastIndex
属性指定的字符处开始检索字符串,当exec()
找到了与表达式相匹配的文本时,在匹配后,它将把RegExp实例的lastIndex
属性设置为匹配文本的最后一个字符的下一个位置。 - 可以通过反复调用
exec()
方法来遍历字符串中的所有匹配文本,当exec()
再也找不到匹配的文本时,它将返回null,并把lastIndex
属性重置为0
- 当正则对象为全局匹配,执行
var reg=/\d/g;
while(r=reg.exec('a1b2c3')){
console.log(r.index+':'+r[0]); //"1:1" "3:2" "5:3"
}
3. 字符串对象实例的方法
String.prototype.search(reg)
search()
方法用于检索字符串中指定的子字符串(参数为子字符串),或检索与正则表达式相匹配的子字符串(参数为正则表达式),返回字符串中第一个匹配的位置,若未找到,返回-1
search()
方法不执行全局匹配,它将忽略标志g
,它同时忽略正则表达式对象的lastIndex
属性,并且总是从字符串的开始进行检索,这意味着它总是返回字符串的第一个匹配的位置
console.log('a1b2c3'.search(/\d/g)); //1
String.prototype.match(reg)
match()
方法将检索字符串,以找到一个或多个与正则匹配的文本
-
非全局匹配的情况
- 如果regexp没有标志
g
,那么match()
方法就只能在字符串中执行一次匹配。如果没有找到任何匹配的文本,match()
将返回null。否则它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。 - 返回的结果数组的第一个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本(如果有的话)
- 如果regexp没有标志
-
全局匹配的情况
- 如果regexp具有标志
g
,则match()方法将执行全局检索,找到字符串中的所有匹配子字符串,若没有找到任何匹配的子串,则返回 null。 - 如果找到了一个或多个匹配子串,则返回一个数组
- 如果regexp具有标志
var reg = /\d(\D)/;
console.log('a1b2c3'.match(reg)); //["1b", "b"]
var reg = /\d(\D)/g;
console.log('a1b2c3'.match(reg)); //["1b", "2c"]
字符串match()方法和正则exec()方法的区别
- match()是字符串的方法,参数是正则;exec()是正则的方法,参数是字符串
- 非全局匹配情况下,二者结果相同
- 全局匹配且无子表达式情况下,exec()执行一次得到的是第一个匹配的结果,要想获得所有结果,需要进行遍历;而match()得到的是所有匹配结果组成的数组
- 全局匹配且有子表达式的情况下,exec()执行一次得到的是第一个匹配到的结果和所有子表达式结果组成的数组,而match()方法会忽略子表达式,返回的是所有匹配到的结果组成的数组
//非全局且无子表达式
var reg = /\D\d/;
var str = 'a1b2c3';
console.log(reg.exec(str)); //["a1"]
console.log(str.match(reg)); //["a1"]
//非全局且有子表达式
var reg = /\D(\d)/;
var str = 'a1b2c3';
console.log(reg.exec(str)); //["a1", "1"]
console.log(str.match(reg)); //["a1", "1"]
//全局且无子表达式
var reg = /\D\d/g;
var str = 'a1b2c3';
console.log(reg.exec(str)); //["a1"]
console.log(reg.exec(str)); //["b2"]
console.log(str.match(reg)); //["a1", "b2", "c3"]
//全局且有子表达式
var reg = /\D(\d)/g;
var str = 'a1b2c3';
console.log(reg.exec(str)); //["a1", "1"]
console.log(reg.exec(str)); //["b2", "2"]
console.log(str.match(reg)); //["a1", "b2", "c3"]
String.prototype.replace(reg|substr, replaceStr|function)
字符串替换方法,返回一个由替换值(参数2)替换匹配的模式(参数1)后的新字符串
- 不改变原字符串
- 有两个参数
- 第一个参数是要替换的部分,可以传入正则表达式或者字符串
- 第二个参数是替换为的部分,可以是一个字符串,或者一个回调函数
- 默认情况下只替换匹配到的第一个,除非在正则中使用修饰符
g
1. 第二个参数为字符串的情况
第二个参数中,如果是字符串,可以使用如下几个特殊模板字符
-
$$
插入一个 "$"。 -
$&
插入匹配的子串。 - $`插入当前匹配的子串左边的内容。
-
$'
插入当前匹配的子串右边的内容。 -
$n
假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第n个子表达式。注意:索引是从1开始
var str = 'abc123def';
var reg = /(\d)\d(\d)/;
console.log(str.replace('123', '$$')); //"abc$def"
console.log(str.replace('123', '0$&4')); //"abc01234def"
console.log(str.replace('123', '$`')); //"abcabcdef"
console.log(str.replace('123', "$'")); //"abcdefdef"
console.log(str.replace(reg, '$1' + '0' + '$2')); //"abc103def"
例子1:给两个单词交换位置
//交换两个单词位置
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr); // Smith, John
2. 第二个参数为函数的情况
str.replace(reg, fn)
可以指定一个函数作为第二个参数,该函数的返回值作为替换字符串,当匹配执行后,该函数就会执行
注意:如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,即每次匹配都会被调用
该回调函数可以接收四个参数
- 参数1:就是匹配到的字符串(类似上述模板字符的$&)
- 参数2(可能有多个,取决于正则中是否有分组):如果参数1是正则且有分组,则参数2就是对应的一个或者多个分组结果
- 参数3:是被匹配到的子串在字符串中的索引位置
- 参数4:原字符串
例子2:将字符串中的每个数字后添加0
var str = 'a1b2c3d4';
var newStr = str.replace(/\d/g, function(match, index, str){
//因为全局匹配会匹配到4次,因此会执行4次console.log()
//match四次分别输出:"1" "2" "3" "4"
//index四次分别输出:1 3 5 7
//str每次都输出:"a1b2c3d4"
console.log(match, index, str);
return match + 0; //给每个匹配到的字符串后面添加个0,作为新字符串
});
console.log(newStr); //"a10b20c30d40"
例子3:给不同分组间添加'-'
function replacer(match, p1, p2, p3) {
//p1、p2、p3表示正则中匹配到的分组(子表达式)
console.log(p1, p2, p3); //"abc" "123" "#$*"
return p1 + '-' + p2 + '-' + p3;
}
var newString = 'abc123#$*'.replace(/([\D]*)(\d*)([\W]*)/, replacer);
console.log(newString); // abc-123-#$*
String.prototype.split(reg)
分割字符串,当字符串作为参数无法满足要求时,也可以传入正则对象作为参数,来将字符串分割为数组
'a1b2c3d'.split(/\d/); //["a", "b", "c", "d"]