Skip to content

第二章 (位置篇)

正则表达式是匹配模式,要么匹配字符,要么匹配位置.请记住这句话

内容包括

  • 什么是位置

  • 如何匹配位置

  • 位置的特性

  • 几个应用实例分析

什么是位置呢?

位置(锚)就是相邻字符之间的位置.比如下图中箭头所指的地方

如何匹配位置呢

在 ES6 中,共有6个锚

^,$,\b,\B,(?=p),(?!p)

相应的可视化形式是:

$^

  • ^(脱字符)匹配开头,在多行匹配中匹配行开头

  • $(美元符号)匹配结尾,在多行匹配中匹配行结尾

比如我们把字符串的开头和结尾用#替换下(位置可以替换成字符的!):

js
var result = "hello".replace(/^|$/g, "#");
console.log(result);
// => "#hello#"

多行匹配模式(即有修饰符 m)时,二者是行的概念,这一点需要我们注意:

js
var result = "I\nlove\njavascript".replace(/^|$/gm, "#");
console.log(result);
/*
#I#
#love#
#javascript#
*/

\b\B

\b 是单词边界,具体就是 \w\W 之间的位置,也包括 \w ^ 之间的位置,和 \w$ 之间的位置。

比如考察文件名 "[JS] Lesson_01.mp4" 中的 \b,如下:

bash
var result = "[JS] Lesson_01.mp4".replace(/\b/g, '#');
console.log(result);
// => "[#JS#] #Lesson_01#.#mp4#"

INFO

为什么是这样呢?这需要仔细看看

首先,我们知道,\w 是字符组 [0-9a-zA-Z_] 的简写形式,即 \w 是字母数字或者下划线的中任何一个字 符。而 \W 是排除字符组 [^0-9a-zA-Z_] 的简写形式,即 \W 是 \w 以外的任何一个字符。

此时我们可以看看 "[#JS#] #Lesson_01#.#mp4#" 中的每一个井号 ,是怎么来的。 第 1 个,两边字符是 "[" 与 "J",是 \W 与 \w 之间的位置。 第 2 个,两边字符是 "S" 与 "]",也就是 \w 与 \W 之间的位置。 第 3 个,两边字符是空格与 "L",也就是 \W 与 \w 之间的位置。 第 4 个,两边字符是 "1" 与 ".",也就是 \w 与 \W 之间的位置。 第 5 个,两边字符是 "." 与 "m",也就是 \W 与 \w 之间的位置。 第 6 个,位于结尾,前面的字符 "4" 是 \w,即 \w 与 $ 之间的位置。

知道了 \b 的概念后,那么 \B 也就相对好理解了。

\B 就是 \b 的反面的意思,非单词边界。例如在字符串中所有位置中,扣掉 \b,剩下的都是 \B 的。

具体说来就是 \w\w\W\W^\W\W$ 之间的位置

比如上面的例子,把所有 \B 替换成 "#":

bash
var result = "[JS] Lesson_01.mp4".replace(/\B/g, '#');
console.log(result);
// => "#[J#S]# L#e#s#s#o#n#_#0#1.m#p#4"

(?=p)和(?!p)

(?=p)其中 p 就是一个子模式,及 P 前面的位置.或者说该位置后面的字符要匹配 p

比如(?=l) 表示l字符前面的位置

javascript
var result = "hello".replace(/(?=l)/g, "#");
console.log(result);
// => "he#l#lo"

(?!p)就是(?=p)的反面意思

javascript
var result = "hello".replace(/(?!l)/g, "#");
console.log(result);
// => "#h#ell#o#"

二者的学名分别是 positive lookahead 和 negative lookahead。 中文翻译分别是正向先行断言和负向先行断言。 ES5 之后的版本,会支持 positive lookbehind 和 negative lookbehind。 具体是 (?<=p) 和 (?<!p)。 也有书上把这四个东西,翻译成环视,即看看右边和看看左边。 但一般书上,没有很好强调这四者是个位置。 比如 (?=p),一般都理解成:要求接下来的字符与 p 匹配,但不能包括 p 匹配的那些字符。

而在本人看来,(?=p) 就与 ^ 一样好理解,就是 p 前面的那个位置。