本文已参与「新人创作礼」活动,一起开启掘金创作之路
javaScript的String对象有几个方法可以是使用正则表达式做为参数,现将这几个方法总结一下防止忘记。
前置知识
文章论述内容默认读者已经掌握了以下知识:
①正则表达式
②String对象的系列相关方法
1、替代->replace/replaceAll
语法:str.replace/replaceAll(substr|regexp,replacement)
接收两个参数:第一个参数是要被替换目标子字符串或者一个正则表达式,第二个参数是一个字符串或者一个函数
返回值:返回一个新的字符串,这个字符串是用 replacement 替换了 regexp 的第一次匹配或所有匹配之后得到的。
参数分析
substr/regexp:replace函数会先根据substr/regexp进行查找匹配,再进行替换。如果regexp是g模式,则会替换所有匹配的子串(这时replace和replaceAll功能是相同的),否则replace只会替换掉匹配的第一个子串。
replacement:如果是字符串,则匹配的子串会由这个字符串替代,而且这时replacement中的$符号具有特殊的意义:
| 字符 | 意义 |
|---|---|
| $1,$2,$3...$n | 指代与regexp中第1,2,3...n个原子组相匹配的文本 |
| $& | 指代与regexp相匹配的子串 |
| $` | 指代匹配子串的左侧的文本 |
| $' | 指代匹配子串的右侧的文本 |
| $$ | 再次转义,指普通的$字符 |
如果replacement是函数,则每次匹配到符合substr/regexp条件的子字符串,都会调用一次函数,且函数的返回值就是替换文本。
函数有参数,存在Arguments伪数组中,第一个参数是匹配到的子字符串,后面的参数依次是正则表达式中匹配到的每个原子组,这些参数可有0~n个。倒数第二个参数是匹配子串在原字符串中的下标,最后一个参数是原字符串。
封装一个函数来实验一下:
let str = '1###test1***demo2';
let reg = /([a-z]+)(\d+)/;
let regGlobal = /([a-z]+)(\d+)/g;
function replaceTest(str, reg) {
let args = [];
str.replace(reg, function () {
args = arguments;
})
return {
'args': args,
'strreplaced': str.replace(reg, "_____($&,$1,$2,$`,$',$$1)____")
}
}
let rep = replaceTest(str, reg);
console.log(rep)
/*
结果:
{
args: Arguments(5) ['test1', 'test', '1', 4, '1###test1***demo2', callee: ƒ, Symbol(Symbol.iterator): ƒ],
strreplaced: "1###_____(test1,test,1,1###,***demo2,$1)____***demo2"
}
*/
2、匹配->match/matchAll
语法: str.match/matchAll(substr|regexp)
参数: 一个字符串或者一个正则表达式
返回值: 一个至多个数组,数值存放了匹配结果,如果没匹配到,则返回null
函数分析
①str.match(substr)返回一个数组,保存了第一个匹配到的子串,同时还有几个特殊属性:
index:匹配到的子串在源字符串str中的下标
input:源字符串str
groups:保存有别名的原子组\
let str = '1###test1***demo2';
function matchTest(str, reg) {
return str.match(reg);
}
console.log(matchTest(str, 1))
//['1', index: 0, input: '1###test1***demo2', groups: undefined]
②str.matchAll(substr)返回一个迭代器,使用这个迭代器会依次迭代str中所有与substr相匹配的子串。
let str = '1###test1***demo2';
function matchTestAll(str, reg) {
return str.matchAll(reg);
}
console.log(...matchTestAll(str, 1))
/*
结果:
['1', index: 0, input: '1###test1***demo2', groups: undefined]
['1', index: 8, input: '1###test1***demo2', groups: undefined]
*/
③str.match(regexp)功能与正则对象的exec方法比较类似,根据regexp是否开启g模式,分两种情况:
a.未开启g模式下,返回的结果的数据结构与str.match(substr)相同。此外如果regexp有原子组,则会将匹配的字符串和匹配原子组的子串依次存入数组,而且此时,str.match(regexp)等同于regexp.exec(str)。
b.开启g模式后,返回一个数组,里面保存str中所有与regexp匹配的子串,但是这个数组没有index、input、groups这些属性。\
let str = '1###test1***demo2';
let reg = /([a-z]+)(\d+)/;
let regGlobal = /([a-z]+)(\d+)/g;
console.log(matchTest(str, reg));
//['test1', 'test', '1', index: 4, input: '1###test1***demo2', groups: undefined]
console.log(matchTest(str, regGlobal));
//['test1', 'demo2']
④str.matchAll(regexp)此时参数regexp必须开启g模式,否则会报错,结果同样返回一个迭代器,可以迭代输出所有与regexp匹配的子串。\
let str = '1###test1***demo2';
let reg = /([a-z]+)(\d+)/;
let regGlobal = /([a-z]+)(\d+)/g;
function matchTestAll(str, reg) {
return str.matchAll(reg);
}
//console.log(...str.matchAll(reg))
// Uncaught TypeError: String.prototype.matchAll called with a non-global RegExp argument
console.log(...str.matchAll(regGlobal))
/*
结果:
(3) ['test1', 'test', '1', index: 4, input: '1###test1***demo2', groups: undefined]
(3) ['demo2', 'demo', '2', index: 12, input: '1###test1***demo2', groups: undefined]
*/
在使用正则表达式的情况下,str.matchAll(regGlobal),比str.match(regGlobal)有明显的优势。
match只是返回一个包含了所有匹配子串的数组。
matchAll则是一个迭代器,可以返回每个匹配子串的详细信息,保留了匹配原子组的子串,以及index、input、groups等属性,这些都是可能的重要信息。\
3、搜索->search
语法: str.search(substr/regexp)
参数: 一个字符串或者一个正则表达式
返回值: 返回与substr/regexp匹配的第一个子串的下标,数值类型
function searchTest(str, reg) {
return str.search(reg)
}
let str = '1###test1***demo2';
let reg = /([a-z]+)(\d+)/;
let regGlobal = /([a-z]+)(\d+)/g;
console.log(searchTest(str, 1)) //1
console.log(searchTest(str, reg)) //4
console.log(searchTest(str, regGlobal)) //4
console.log(typeof searchTest(str, reg)) //number
不难发现它只能得到匹配到的第一个子串的下标,即使regexp开启了g模式也搜索不到第二个。\
4、分割->split
语法: str.split(substr|regexp,limit)
参数: 第一个参数是一个字符串或者一个正则表达式,第二个参数是可选的整数limit
返回值: 返回数组。split方法让str以参数substr或者regexp的规则进行分割,然后将分割后得到的每个子串存放在数组里面返回,参数limit可以控制这个数组的长度。
function splitTest(str, reg, limit) {
return str.split(reg, limit);
}
let str = '1###test1***demo2';
let reg3 = /[a-z*#]+/;
console.log(splitTest(str, reg3)); //['1','1','2']
console.log(splitTest(str, reg3, 2)); //['1','1']