【玩转正则_2】位置

532 阅读2分钟

一个字符串,由字符和位置组成,正则世界的奥妙离不开这两者。以下将围绕位置的要点进行说明。

1 什么是位置

位置即字符间相邻的点;位置本身不占空间,可以理解为空字符

hello == "" + h + "" + e + "" + l + "" + l + "" + o + "";

Untitled.png

注意收尾都会有空字符,对应着^、$

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, '#') );
  1. 多行匹配模式以 [\n\r\u2028\u2029] 字符对字符串进行分行,很熟悉,前文说到的 通配符. 的范围是:[^\n\r\u2028\u2029]
  2. 正则修饰符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) 可以限制该位置后的字符串内容;

Untitled.png

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 无法直接与重复符号(+、*等)一起使用,/^+/ 该正则没有意义将会报错;