第二章 (位置篇)
正则表达式是匹配模式,要么匹配字符,要么匹配位置.请记住这句话
内容包括
什么是位置
如何匹配位置
位置的特性
几个应用实例分析
什么是位置呢?
位置(锚)就是相邻字符之间的位置.比如下图中箭头所指的地方
如何匹配位置呢
在 ES6 中,共有6
个锚
^
,$
,\b
,\B
,(?=p)
,(?!p)
相应的可视化形式是:
$
和^
^
(脱字符)匹配开头,在多行匹配中匹配行开头$
(美元符号)匹配结尾,在多行匹配中匹配行结尾
比如我们把字符串的开头和结尾用#
替换下(位置可以替换成字符的!):
var result = "hello".replace(/^|$/g, "#");
console.log(result);
// => "#hello#"
多行匹配模式(即有修饰符 m)时,二者是行的概念,这一点需要我们注意:
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
,如下:
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 替换成 "#":
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
字符前面的位置
var result = "hello".replace(/(?=l)/g, "#");
console.log(result);
// => "he#l#lo"
而(?!p)
就是(?=p)
的反面意思
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 前面的那个位置。