正则学习(四)-正则表达式中的位置匹配

2023-12-25 11:06:32

正则表达式的匹配要么匹配字符,要么匹配位置。

字符比较理解,那么什么是位置呢?

一. 位置

相邻字符之间的空隙,可以被称为位置,也被称为锚。开头和第一个字符之间、结束和最后一个字符之间,也被称为位置。

比如下图红色箭头位置:

字符串:"ab abc abcd abcde"

二. 如何匹配位置

1. ^

^ 被称为脱字符,表示开头位置,需要注意的是,如果匹配时支持多行匹配,此时匹配多行的开头。

比如下图中红色箭头位置:

(1)匹配单行

const str = `
  I
  am
  a
  teacher
`;
str.replace(/^/g, "#");

结果:

#
  I
  am
  a
  teacher

(2)匹配多行

str.replace(/^/gm, "#");

结果:

#
#  I
#  am
#  a
#  teacher
#

2. $

$ 被称为dollar符(美元符),表示结束位置,需要注意的是,如果匹配时支持多行匹配,此时匹配多行的结束位置。

比如下图中红色箭头位置:

(1)匹配单行

const str = `
  I
  am
  a
  teacher
`;
str.replace(/$/g, "#");

结果:


  I
  am
  a
  teacher
#

(2)匹配多行

str.replace(/$/gm, "#"); 

结果:

#
  I#
  am#
  a#
  teacher#
#

3. \b

\b 表示单词边界,\w 和 \W 之间的位置,也包含 \w 和 ^ 之间的位置,还有 \w 和 $ 之间的位置。

\w 表示数字、大小写字母和_,\w是字符组[0-9a-zA-Z_]的简写表示。\W是除了\w外的其他字符。

比如,字符串 "I am a teacher":

红色箭头就是这个字符串的单词边界。

举例,我们将这个字符串的单词边界位置替换成 $ :

const str = "I am a teacher";
str.replace(/\b/g, "$"); // "$I$ $am$ $a$ $teacher$"

4. \B

\B 表示非单词边界,排除掉的位置,其他都是非单词边界。

具体是\w 和 \w 之间的位置,\W 和 \W 之间的位置,^ 和 \W 之间的位置,\W 和 $ 之间的位置。

比如,字符串 "I am a teacher":

红色箭头就是这个字符串的非单词边界。

举例,我们将这个字符串的单词边界位置替换成 $ :

const str = "I am a teacher";
str.replace(/\B/g, "$"); // "I a$m a t$e$a$c$h$e$r"

5. (?=p)

(?=p) 被称为正向先行断言,p是一个子模式,表示匹配了p子模式前面的位置。

比如,字符串 "I am a teacher",我们需要在teacher前面添加一个 $ :

红色箭头位置即是,如下图所示:

const str = "I am a teacher";
str.replace(/(?=teacher)/g, "$"); // "I am a $teacher"

6. (?!p)

(?!p) 被称为负向先行断言,是(?=p)的反面位置(排除(?=p)的位置外的所有位置)。

比如,字符串 "I am a teacher" :

红色箭头就是,如下图所示

const str = "I am a teacher";
str.replace(/(?!teacher)/g, "$"); // "$I$ $a$m$ $a$ t$e$a$c$h$e$r$#"

如果没有匹配到,那所有位置都需要替换成 $ 。

const str = "I am a teacher";
str.replace(/(?!red)/g, "$");
// $I$ $a$m$ $a$ $t$e$a$c$h$e$r$

7. (?<=p)

(?<=p) 是匹配了p子模式后面的位置。

比如,字符串 "I am a teacher",我们需要在teacher后面添加一个 $ :

const str = "I am a teacher";
str.replace(/(?<=teacher)/g, "$"); // "I am a teacher$"

8. (?<!p)

(?<!p) 是除了匹配了p子模式后面的位置外,其他所有位置。

比如,字符串 "I am a teacher" :

const str = "I am a teacher";
str.replace(/(?<!teacher)/g, "$"); // "$I$ $a$m$ $a$ $t$e$a$c$h$e$r"

三. 案例

数字千分位用逗号(,)分隔,比如:1000,表示成1,000

const str = "1000";
str.replace(/(?!^)(?=(\d{3})+$)/g, ","); // "1,000"

解析:

(?!^):表示排除开始位置

(?=(\d{3})+$):匹配\d{3}$的前面位置,匹配\d{6}$的前面的位置,...,匹配\d{3n}的前面位置。

千分位的分割从尾数开始算。

上面的正则,可以很好的匹配整数金额,但是如果有小数,小数前面的整数千分位分割就会失效。

第一种方法,你可以在将小数点加入正则中 :

const str = "4444415555.4444";
str.replace(/(?!^)(?<!\.)(?=(\d{3})+($|\.))/g, ","); // "4,444,415,555.4,444"

目前我们是将小数点加入,但是扩展性比较差,如果小数点变成空格呢?

第二种方式:

无论开始位置,还是小数点位置,或者结束位置,又由于只是针对数字,其实都可以统一认为是单词边界。

const str = "4444415555.4444";
str.replace(/(?!\b)(?=(\d{3})+\b)/g, ","); // "4,444,415,555.4,444"

目录

相关推荐
正则学习(一)-什么是正则表达式,及如何创建正则表达式正则学习(二)- 常用元字符:量词和字符组正则学习(三)-正则中不得不说的捕获和反向引用正则学习(五)-深入理解String.prototype.replace正则学习(六)- 贪婪模式和惰性模式