跳到主要内容

正则

正则

正则表达式(Regular Expression)描述了字符串的匹配模式(pattern)。 基于正则表达式扩展出 『扩展正则表达式』(Extended Regular Expression,ERE)和『POXIS 扩展正则表达式』(POXIS ERE)。 JavaScript 中的正则属于 ERE。 基础的正则知识可以看这里

什么是贪婪?

对于量词 {n,m} 能匹配的次数大于 n 次就会尽可能匹配多次,直到最多 m 次。

什么是先行、后行、正向、负向断言

先行 lookahead

后行 lookbehead

正向 positive

负向 negtive

举个例子

const str1 = "foo fuu";
const str2 = "oof uuf";

// 正向先行 匹配 f 后面紧接着 oo
const reg1 = /f(?=oo)/;
// 负向先行 匹配 f 后面紧接着不是 oo
const reg2 = /f(?!oo)/;
// 正向后行 匹配 f 前面紧接着 oo
const reg3 = /(?<=oo)f/;
// 负向后行 匹配 f 前面紧接着不是 oo
const reg4 = /(?<!oo)f/;

console.log(reg1.exec(str1));
console.log(reg2.exec(str1));
console.log(reg3.exec(str2));
console.log(reg4.exec(str2));

先行和后行匹配的是字符命中的是位置,先行命中左边,后行命中右边,他们在匹配的过程中并不消耗字符串

Lookahead and lookbehind, collectively called “lookaround”, are zero-length assertions just like the start and end of line. The difference is that lookaround actually matches characters, but then gives up the match, returning only the result: match or no match. That is why they are called “assertions”. They do not consume characters in the string, but only assert whether a match is possible or not.

【参考】

const leftAssertaion = "hello".replace(/(?=l)/g, "#"); // 'he#l#lo'
const leftAssertaion = "hello".replace(/(?<=l)/g, "#"); // 'hel#l#o'

什么是反向引用

可以用来查找 AABB、BBAA 类型的字符

const str = "d1122jj7667h6868s9999";
//查找AABB型的数字
console.log(str.match(/(\d)\1(\d)\2/)); //1122
//查找ABBA型的数字
console.log(str.match(/(\d)(\d)\2\1/)); //7667
//查找ABAB型的数字
console.log(str.match(/(\d)(\d)\1\2/)); //6868
//查找四个连续相同的数字
console.log(str.match(/(\d)\1\1\1/)); //9999

String.prototype.replace()

replace 被称为是最强大的字符串方法。

str.replace(regexp|substr, newSubStr|function)

其中,

regexp (pattern) 一个RegExp 对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。

substr (pattern) 一个将被 newSubStr 替换的 字符串。其被视为一整个字符串,而不是一个正则表达式。仅第一个匹配项会被替换。

newSubStr (replacement) 用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。参考下面的使用字符串作为参数。

function (replacement) 一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。参考下面的指定一个函数作为参数。

使用字符串作为参数

\$\$ 插入一个 "$"。 \$\& 插入匹配的子串。 \$` 插入当前匹配的子串左边的内容。 $' 插入当前匹配的子串右边的内容。 $n 假如第一个参数是 RegExp对象,并且 n 是个小于 100 的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从 1 开始。如果不存在第 n 个分组,那么将会把匹配到到内容替换为字面量。比如不存在第 3 个分组,就会用“$3”替换匹配到的内容。 $\<Name> 这里Name 是一个分组名称。如果在正则表达式中并不存在分组(或者没有匹配),这个变量将被处理为空字符串。只有在支持命名分组捕获的浏览器中才能使用。

但是使用字符串有点违反直觉。如果有需要使用上述的特殊变量,我更推荐使用函数:

function replacer(match, p1, p2, p3, offset, string) {
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString); // abc - 12345 - #$*%

match 匹配的子串。(对应于上述的$&。) p1,p2, ... 假如 replace() 方法的第一个参数是一个RegExp 对象,则代表第 n 个括号匹配的字符串。(对应于上述的$1,$2 等。)例如,如果是用 /(\a+)(\b+)/ 这个来匹配,p1 就是匹配的 \a+,p2 就是匹配的 \b+。 offset 匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 'abcd',匹配到的子字符串是 'bc',那么这个参数将会是 1) string 被匹配的原字符串。 NamedCaptureGroup 命名捕获组匹配的对象

参考