一个字符串,由字符和位置组成,正则世界的奥妙离不开这两者。以下将围绕位置的要点进行说明。
1 什么是位置
位置即字符间相邻的点;位置本身不占空间,可以理解为空字符:
hello == "" + h + "" + e + "" + l + "" + l + "" + o + "";
注意收尾都会有空字符,对应着^、$
tips: 因为位置并不占位,通过正则匹配出来也是空字符串,它的使用大多:
1、通过replace方法,在位置中插入字符;
2、与字符结合使用,限制该位置左右的字符串内容;
2 如何匹配位置
通过 ^、$、\b、\B、(?=p)、(?!p) 匹配具体的位置;
2.1 ^ 和 $
^(脱字符) 在多行中,匹配行开头;
$(美元符号) 在多行中,匹配刚结尾;
var regexp = /^|$/g;
var string = 'abc\nabc\nabc';
// #abc\nabc\nabc#
console.log( string.replace(regexp, '#') );
可以看见的是,的确在首尾位置替换为了#字符,但是“多行”的含义体现在哪里呢?
这是因为两字符默认不是多行匹配,需要通过 正则修饰符m 开启多行匹配模式。
var regexp = /^|$/gm;
var string = 'abc\nabc\nabc';
// #abc#\n#abc#\n#abc#
console.log( string.replace(regexp, '#') );
var regexp = /a/g;
var string = 'abc\nabc\nabc';
// #bc\n#bc\n#bc
console.log( string.replace(regexp, '#') );
- 多行匹配模式以
[\n\r\u2028\u2029]字符对字符串进行分行,很熟悉,前文说到的 通配符. 的范围是:[^\n\r\u2028\u2029];正则修饰符m是仅针对脱字符^和美元符号$有作用(其余字符都是多行匹配);
2.2 \b 和 \B
\b是单词边界,具体就是 \w([0-9a-zA-Z_]) 和 \W 之间的位置、\w 和 ^ 之间的位置、\w 和 $ 之间的位置;
var regexp = /\b/g;
var string = 'rengar xiao_1';
// #rengar# #xiao_1#
console.log( string.replace(regexp, '#') );
问题1:在初学的过程中,如何将所有的位置替换为#字符,方便观察?
/\b|\B/g可以表示所有的位置;
对比之下,/\b\B/g,不匹配任何位置;
2.3 (?=p) 和 (?!p)
(?=p) 学名为 positive lookhead,正向先行断言,其中p代表字符串,(?=p) 代表p前面的位置,位置后面即是字符串p,可视化如下:
(?=p)可以限制该位置后的字符串内容;
var regexp = /(?=r)/g;
var string = 'rengar xiao_1';
// #renga#r xiao_1
console.log( string.replace(regexp, '#') );
(?!p) 反向理解,即该位置后面不能是字符串p;
问题1:那么如何限制该位置前方的字符串内容呢?
通过(?<=p)负向先行断言,但是该API需要更高的语言版本支持;问题2:
(p)和(?:p)的区别是什么?
前者匹配单个字符p,后者匹配的是空字符;
2.4 位置符号的或与并
接下來,结合字符的要点,同位置进行对比理解:
(1)或&
前面提到位置,可以理解为空字符“”,在正则中,/^^^/ 和 /^/ 是相同的含义,字符之间的位置,可以使用多个表示位置;
- 在字符中,
/aaa/匹配的是三个字符a; - 在字符中,
/[abc]/匹配的是一个字符,可能是a、b、c; - 在位置中,
/^\\b$/匹配的是一个位置,可以理解为对同一个位置的多个限制条件;
(2)与|
有时,想匹配位置有多种情况,可能是 ^,可能是 \b,这时可以通过分支书写:/^|\\b/ 表示,这点同字符相同;
2.5 位置在范围表示法
在前文中,范围表示法是通过 [] 中书写字符:
(1)^字符,如果在首位则表示排除表示 /[^]/,否则将表示字符本身;
(2)$字符、\b字符、\B字符,在范围中表示字符本身;
(3)(?=p) 在范围中表示字符p本身;
var regexp = /[$^\b\B(?=a)]/g;
var string = 'abc$^cb\b\B';
// #bc##cb##
console.log( string.replace(regexp, '#') );
2.6 位置在重复表示法
位置字符 ^、$、\b、\B 无法直接与重复符号(+、*等)一起使用,/^+/ 该正则没有意义将会报错;