目录
19-1 使用字符类编写匹配不同字符的模式
19-2 编写一个匹配字符串开头或结尾等位置的模式
19-3 编写一个模式,匹配一个重复前面的字符指定次数的字符串
19-4 编写匹配多个字符串中任意一个的模式
19-5 设置捕获组以获取匹配部分模式的字符串
19-6 使用 lookahead 和 lookbehind 编写模式
解释如何使用字符类,它们是可在 JavaScript 中使用的正则表达式元字符之一。一个字符类除了可以描述一个固定的字符串外,还可以描述一个匹配任意单个字符的模式,或者匹配多个候选字符中的任意一个的模式。
匹配指定字符
如果您在模式中写入一个字符,它会匹配该字符本身。例如,以下模式匹配任何以 A 开头、然后是 B 并以 C 结尾的字符串。
const regexp = /ABD/;
匹配 ABC 、 OABC 、 ABCE 等。与 AIBD 或 AB 不匹配。
〇 ABC
〇 ABCDEF
〇 PABC
✕ AIBD
✕ AB
示例代码
用一个简单的例子来尝试。
let regexp = /Sun/;
console.log(regexp.test('Today is Sunday'));
>> true
console.log(regexp.test('The Sun rose'));
>> true
console.log(regexp.test('Ham Sandwich'));
>> false
任何单个字符 (.)
元字符之一,点 (.),匹配任何单个字符(有例外)。
.
※ 但是,它不匹配以下字符。
\n
\r
\u2028 # Line Separator
\u2029 # Paragraph Separator
例如,以下模式将匹配任何以 A 开头后跟任何单个字符后跟 B 的字符串:
const regexp = /A.B/;
匹配 AOB 和 AED。不匹配 ATYB 或 AB。
〇 AOB
〇 A#B
〇 WWAmBEE
✕ ADDB
✕ AB
像下面这样的模式将匹配任何以 A 开头,后跟任意两个字符,再后跟 B 的字符串:
const regexp = /A..B/;
〇ATTB
〇 O AmnB W
✕ AVB
✕ APPPB
以下模式与单词边界元字符 \b 相结合,匹配任何字符的三字母单词。
const regexp = /\b...\b/;
〇 Blue Red Yellow
示例代码
我会用一个简单的例子来尝试。
let regexp = /S..d/;
console.log(regexp.test('Today is Sunday'));
>> true
console.log(regexp.test('The Sun rose'));
>> false
console.log(regexp.test('Ham Sandwich'));
>> true
方括号中的单个字符 ([…])
方括号 ([…]) 是用于匹配方括号内的任何一个字符的元字符。
[...]
例如,以下模式匹配以 A 开头的任何字符串,后跟写在 [ 和 ] 之间的 D 、 E 或 F 中的任何一个,然后是 B 。
const regexp = /A[DEF]B/;
匹配 ADB 和 AEB。与 AOB 或 AdB 不匹配。
〇 ADB
〇 AEB
〇 wAFBw
✕ AOB
✕ AdB
示例代码
我会用一个简单的例子来尝试。
let regexp = /[sS]un/;
console.log(regexp.test('Today is Sunday'));
>> true
console.log(regexp.test('The Sun rose'));
>> true
console.log(regexp.test('Ham Sandwich'));
>> false
方括号的否定
如果在方括号([…])的开头写一个插入符(^)表示否定,则如果方括号内写的多个字符都不匹配,则匹配。
[^...]
例如,以下模式匹配以 A 开头的任何字符串,后跟一个与 [to] 中的 D 、 E 或 F 中的任何一个都不匹配的单个字符,然后是 B 。
const regexp = /A[^DEF]B/;
请注意,它不仅否定紧跟在 ^ 之后的字符,而且否定写在 [ 和 ] 之间的所有字符。
匹配 AOB 和 AdB。与 ADB 或 AEB 不匹配。
〇 AOB
〇 AdB
〇 wA8Bw
✕ ADB
✕ AEB
示例代码
用一个简单的例子来尝试。
let regexp = /199[^01234]/;
console.log(regexp.test('My birthday is 1998/03/12'));
>> true
console.log(regexp.test('Graduated in 1994'));
>> false
console.log(regexp.test('It opened in 1996'));
>> true
方括号范围规范
方括号 ([…]) 内的连字符 (-) 匹配连字符从左到右范围内的任何连续字符。例如,你可以写:
[0-9] 0 到 9 之间的任何数字
[a-z] 从 a 到 z 的任意字母
[A-Z] 从 A 到 Z 的任意字母
例如,以下两个模式匹配相同的字符:
const regexp1 = /[3-8]/;
const regexp2 = /[345678]/;
[ 到 ] 中可以写多个范围,并且可以与普通字符规范组合。以下模式匹配任何字符 a 到 e 、 g 、 m 、 x 到 z 。
const regexp1 = /[a-egmx-z]/;
const regexp2 = /[abcdegmxyz]/;
以下符号通常用作匹配任何字母数字字符的模式。
const regexp = /[0-9a-zA-Z]/;
当你想匹配像这样的一系列字符中的任何一个时,这种形式很有用。
示例代码
用一个简单的例子来尝试。
let regexp = /199[0-6]/;
console.log(regexp.test('My birthday is 1998/03/12'));
>> false
console.log(regexp.test('Graduated in 1994'));
>> true
console.log(regexp.test('It opened in 1996'));
>> true
字符类速记
在字符类中,您可以通过描述 [ 到 ] 中的字符范围来描述与许多字符中的任何一个匹配的模式,但特别是经常使用的字符有一个简写符号它已经准备好了。JavaScript 中可用的速记符号是:
\d 数字 [0-9]
\D 非数字 [^\d]
\w 字母数字和下划线 [0-9a-zA-Z_]
\W 字母数字和非下划线 [^\w]
\s 空格字符 [ \ f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]
\S 非空白字符 [ ^\s
]
\D 否定小写版本的大写版本,如 \d 否定。
空白字符匹配等同于空白的字符,例如换行符 (\n) 和制表符 (\t),以及单字节空格。
例如,以下两个模式匹配相同的字符:
const regexp1 = /[0-9]/;
const regexp2 = /\d/;
匹配的字符相同,只是符号不同。通过对可用缩写的模式使用缩写,您可以更紧凑地编写模式。
示例代码
用一个简单的例子来尝试。
let str = '邮政编码是 126-7898';
let regexp = /\d{3}-\d{4}/;
let result = str.match(regexp);
console.log(result[0]);
>> 126-7898
换行符等特殊字符
提供了将反斜杠 () 与字符组合在一起的元字符,以编写匹配无法从键盘输入的特殊字符(例如换行符和制表符)的模式。
\0 NULL
\f 分页符
\n 换行符
\r enter
\t tab
\v 垂直tab
\cX Ctrl + x
\xhh 十六进制 hh ASCII 字符
\uhhhh 十六进制hhhh表示的UTF-16编码单元
如果设置了 u 标志,您还可以使用以下元字符:
\u{hhhh}
\u{hhhhh} 十六进制 hhhh 或 hhhhh 表示的 Unicode 代码点
示例代码
我会用一个简单的例子来尝试。
let str = `早上好。
今早的气温很低啊。`;
let regexp = /。\n./;
let result = str.match(regexp);
console.log(result[0]);
>> 。
>> 今
正则表达式提供匹配位置的元字符,例如字符串的开头或结尾、单词边界等,而不是字符本身。例如,如果您使用匹配字符开头的元字符,则它只会匹配从字符开头开始的后面的模式。在这里,我们将解释如何使用 JavaScript 中的正则表达式编写匹配字符串开头和结尾等位置的模式。
匹配字符串的开头 (^)
元字符之一,插入符号 (^),匹配字符串的开头。
^
例如,以下模式将匹配任何从字符串开头开始并以 R 开头,后跟 e 和 d 的字符串。
const regexp = /^Red/;
匹配Red和Reduce。但是,如果不在字符串的开头,即使是Red也不会匹配。
〇 Red Color
〇 Reduce
✕ Radio
✕ Color is Red
示例代码
用一个简单的例子来尝试。
let regexp = /^Red/;
console.log(regexp.test('Red Table'));
>> true
console.log(regexp.test('Reduce speed'));
>> true
console.log(regexp.test('Border Color is Red'));
>> false
匹配字符串的结尾 ($)
元字符之一,美元符号 ($),匹配字符串的末尾。
$
例如,如果字符串 Script 出现在字符串的末尾,则以下模式将匹配。
const regexp = /Script$/;
匹配 JavaScript 和 TypeScript。但是,如果不在字符串的末尾,即使是JavaScript也不会匹配。
〇 JavaScript
〇 I am studying TypeScript
✕ script
✕ PostScript is difficult
示例代码
我会用一个简单的例子来尝试。
let regexp = /Script$/;
console.log(regexp.test('JavaScript'));
>> true
console.log(regexp.test('I am studying TypeScript'));
>> true
console.log(regexp.test('PostScript is difficult'));
>> false
匹配单词的开头和结尾 (\b)
一个元字符 \b 匹配单词的开头和结尾。
\b
例如,如果字符串 work 出现在单词的开头,则以下模式匹配。
const regexp = /\bwork/;
匹配工作或工作。但它不匹配单词开头以外的任何内容,例如 fireworks。
〇 work
〇 a working person
✕ worm
✕ Go to see fireworks
\b不仅匹配单词单词的开头还匹配结尾。例如,如果字符串 ing 出现在单词的末尾,则以下模式匹配。
const regexp = /ing\b/;
适合swimming 和 working。但是,如果不在单词的末尾,则不匹配,例如 ingenious。
〇 swimming
〇 a working person
✕ worm
✕ ingenious design
以下模式分别在单词的开头和结尾使用 \b,仅匹配单词 working。如果它前面或后面有字符,则它不匹配。
const regexp = /\bworking\b/;
示例代码
用一个简单的例子来尝试。
let regexp1 = /\bwork/;
console.log(regexp1.test('a working person'));
>> true
console.log(regexp1.test('Go to see fireworks'));
>> false
let regexp2 = /ing\b/;
console.log(regexp2.test('a working person'));
>> true
console.log(regexp2.test('ingenious design'));
>> false
匹配单词开头和结尾以外的任何内容 (\B)
\B 是元字符之一,匹配单词开头或结尾以外的任何地方。
\B
例如,如果以下模式从单词开头以外的任何位置开始并且后跟 am,则它会匹配。
const regexp = /\Bam/;
匹配sample 和 program 。但是,如果从amount这样的单词开头开始,则匹配不上。
〇 sample
〇 Difficult program
✕ full amount
例如,以下模式匹配字符串 am 之后不是单词结尾的任何位置。
const regexp = /am\B/;
匹配sample 和 amount, 但是,如果 am 在像 program 这样的单词的末尾,它就不会匹配。
〇 sample
〇 full amount
✕ Difficult program
示例代码
用一个简单的例子来尝试。
let regexp1 = /\Bam/;
console.log(regexp1.test('Difficult program'));
>> true
console.log(regexp1.test('full amount'));
>> false
let regexp2 = /am\B/;
console.log(regexp2.test('full amount'));
>> true
console.log(regexp2.test('Difficult program'));
>> false
正则表达式还可以定义匹配字符串的模式,其中前面的字符重复指定次数。次数可以是1次以上,也可以是0次以上,也可以是重复次数。除了字符之外,还可以使用字符类等生成模式。本节介绍如何使用 JavaScript 正则表达式编写模式,以匹配重复字符或其他模式指定次数的字符串。
连续匹配前面的字符 0 次或多次 (*)
星号 (*) 是元字符之一,它与前面的字符连续匹配字符串 0 次或多次(0 次或多次意味着它不出现一次或多次都无关紧要)。
*
例如,以下模式匹配任何以 H 开头,后跟字母 a 零次或多次,再后跟 n 的字符串:
const regexp = /Ha*n/;
匹配 Han 和 Haaaan。它还与 Hn 匹配,因为前面的字符出现 0 次或多次。
〇 Hn
〇 Han
〇 Haaan
〇 Haaaaaaaan
✕ Hen
✕ Ham
✕ HaaUaan
示例代码
我会用一个简单的例子来尝试。
let regexp = /Ha*n/;
console.log(regexp.test('Hn'));
>> true
console.log(regexp.test('Han'));
>> true
console.log(regexp.test('Haaaaan'));
>> true
console.log(regexp.test('HaaUaan'));
>> false
匹配前面的字符一次或多次 (+)
元字符之一,即加号 (+),与任何包含前面字符的字符串匹配一次或多次。
+
例如,以下模式匹配以 H 开头,后跟字母 a 一次或多次,再后跟 n 的任何字符串。
const regexp = /Ha+n/;
匹配 Han 和 Haaaan。不匹配 Hn,因为前面的字符出现一次或多次。
✕ Hn
〇 Han
〇 Haaan
〇 Haaaaaaaan
✕ Hen
✕ Ham
✕ HaaUaan
示例代码
用一个简单的例子来尝试。
let regexp = /Ha+n/;
console.log(regexp.test('Hn'));
>> false
console.log(regexp.test('Han'));
>> true
console.log(regexp.test('Haaaaan'));
>> true
console.log(regexp.test('HaaUaan'));
>> false
匹配前面的字符 0 次或 1 次 (?)
元字符之一,问号 (?),与前面的字符匹配 0 次或 1 次。
?
例如,以下模式匹配任何以 H 开头的字符串,然后是字母零或一次,然后是 n:
const regexp = /Ha?n/;
Hn や Han にはマッチします。直前の文字が 0 回または 1 回なので Haaan にはマッチしません。
〇Hn
〇 Han
✕ Haaan
✕ Hen
✕ Ham
示例代码
用一个简单的例子来尝试。
let regexp = /Ha?n/;
console.log(regexp.test('Hn'));
>> true
console.log(regexp.test('Han'));
>> true
console.log(regexp.test('Haaaaan'));
>> false
console.log(regexp.test('Ham'));
>> false
匹配重复前一个字符 num 次的字符 ({num})
其中一个元字符 {num} 匹配由前面的字符重复 num 次组成的字符串。
{num}
例如,以下模式将匹配任何以 H 开头的字符串,后跟字母 a 三次,然后是 n :
const regexp = /Ha{3}n/;
匹配哈安。它不匹配 Han 或 Haaaaan,因为重复次数是固定的。
〇 Haaan
✕ Han
✕ Haaaaan
示例代码
用一个简单的例子来尝试。
let regexp = /Ha{3}n/;
console.log(regexp.test('Haaan'));
>> true
console.log(regexp.test('Han'));
>> false
console.log(regexp.test('Haaaaan'));
>> false
console.log(regexp.test('HaaaO'));
>> false
匹配重复前一个字符至少 min 次且不超过 max 次的字符 ({min,max})
其中一个元字符 {min,max} 匹配一个字符串,该字符串重复前面的字符至少 min 次且不超过 max 次。您也可以只指定一个或另一个。
{min,} 重复前一个字符至少 min 次
{,max} 重复前一个字符最多 max 次
{min,max} 重复前一个字符最小到最大次数
请注意,如果您在最大值前放置一个半角空格,例如 {2, 4} 而不是 {2, 4},它将不会匹配。
例如,以下模式匹配任何以 H 开头、后跟重复 2 到 4 次的字母 a 和 n 的字符串。
const regexp = /Ha{2,4}n/;
匹配 Haan 或 Haaan 或 Haaaan。它不匹配 Han 或 Haaaaan,因为重复次数是固定的。
〇 Haan
〇 Haaan
〇 Haaaan
✕ Han
✕ Haaaaan
示例代码
用一个简单的例子来尝试。
let regexp = /Ha{2,4}n/;
console.log(regexp.test('Haan'));
>> true
console.log(regexp.test('Haaaan'));
>> true
console.log(regexp.test('Haaaaan'));
>> false
console.log(regexp.test('HaaaO'));
>> false
重复以前的模式
到目前为止所描述的重复元字符不仅匹配前面的字符,还匹配任何重复前面另一个模式的字符串。例如,如果您在表示任何字符的点 (.) 后面紧跟一个星号 (*),它将匹配任何重复任何字符 0 次或多次的字符串。
.*
例如,以下模式匹配任何以 <p> 开头,后跟任意字符零次或多次,并以 </p> 结尾的字符串。
const regexp = /<p>.*<\/p>/;
因为斜线(/)在正则表达式中必须转义,所以用反斜线(\)来写\/。
此外,如果在匹配 0 到 9 中任意字符的字符类中紧跟在 [0-9] 之后写入 {4},它将匹配任意 4 个连续数字的字符串。
[0-9]{4}
例如,以下模式匹配以任何数字出现 3 次、后跟连字符 (-)、最后出现任何数字 4 次的任何字符串。
const regexp = /[0-9]{3}-[0-9]{4}/;
示例代码
我会用一个简单的例子来尝试。
let regexp1 = /<em>.*<\/em>/;
let str1 = '<p>今天是<em>晴朗</em>的一天</p>';
let result1 = str1.match(regexp1);
console.log(result1[0]);
>> <em>晴朗</em>
let regexp2 = /[0-9]{3}-[0-9]{4}/;
let str2 = '邮政编码为126-4568';
let result2 = str2.match(regexp2);
console.log(result2[0]);
>> 126-4568
重复分组模式
到目前为止,重复的目标是可以匹配紧接其前面的字符或模式。
例如,让我们创建一个重复 1 到 3 个数字后跟一个点 (.) 的字符串 3 次的模式。以一到三位数字开头后跟一个点 (.) 的字符串模式可以写成转义为 .)。
const regexp = /\d{1,3}\./;
由于这是一个将整个模式重复三次的模式,而不是简单地添加 {3},因此在将整个目标模式括在括号 () 中后写入 {3} 以对其进行分组。
const regexp = /(\d{1,3}\.){3}/;
这样就完成了由 1 到 3 个数字组成的字符串重复 3 次后跟一个点 (.) 的模式。
示例代码
用一个简单的例子来尝试。
let regexp = /(\d{1,3}\.){3}\d{1,3}/;
let str = 'IP地址为 192.168.0.18 ';
let result = str.match(regexp);
console.log(result[0]);
>> 192.168.0.18
最大量词和最小量词
默认情况下,像 + 和 * 这样的量词会尝试匹配更多的字符串。看看下面的示例。
let regexp = /b.*a/;
let str = 'breakfast is sandwich';
let result = str.match(regexp);
console.log(result[0]);
>> breakfast is sa
此模式匹配任何以 b 开头,后跟零次或多次出现的任何字符后跟 a 的字符串。在目标字符串中,a 出现在 b 之后的位置有 3 个。
breakfast is sandwich
breakfast is sandwich
breakfast is sandwich
我们在前面的示例中所见,实际匹配项是最右侧的 a。这是因为默认情况下,像 +、* 和 {min,max} 这样的量词会尝试匹配更多的字符串。这样的量词称为最大量词。
在使用 + 和 * 等量词时,使用最少的量词来匹配较少的字符串。在每个量词后写一个问号(?)。
*?
+?
??
{min, max}?
让我们使用最小量词重写前面的例子。
let regexp = /b.*?a/;
let str = 'breakfast is sandwich';
let result = str.match(regexp);
console.log(result[0]);
>> brea
在这个例子中,它匹配了最少的可能匹配字符串。
正则表达式允许您描述一组替代字符串,并定义一个模式,如果其中任何一个匹配,该模式将匹配。本节介绍如何编写匹配 JavaScript 正则表达式中多个字符串之一的模式。
匹配多个字符串之一 (|)
元字符之一,竖线 (|),匹配与多个字符串中的任何一个匹配的字符串。写入由竖线 (|) 分隔的候选字符串。
字符串|字符串|...
例如,以下模式将匹配任何匹配 Sunday 或 Sun 或 sunday 的字符串。
const regexp = /Sunday|Sun|sunday/;
匹配Sunday , Sun , sunday 。它还匹配包含任何这些字符串的字符串,因为在它之前或之后没有其他模式。
〇 Go out on sunday
〇 Today is Sunday
〇 Sunflowers are in bloom
示例代码
用一个简单的例子来尝试。
let regexp = /Sunday|Sun|sunday/;
console.log(regexp.test('Today is Sunday'));
>> true
console.log(regexp.test('Sunflowers are in bloom'));
>> true
console.log(regexp.test('SUNDAY MORNING'));
>> false
用括号将多项选择分组
如果您编写的模式与多个字符串替代项中的一个匹配,那么如果您将它与之前或之后的另一个模式组合,则不能按原样编写。比如你试着在red或者red的选择前后加上\b,它是一个词的边界,如果你这样写,就会是一个选择\bRed或者re\b。
const regexp = /\bRed|red\b/;
因此,我们将选项部分括在括号()中,对它们进行分组。通过分组,您可以明确选项部分的开始和结束位置。
const regexp = /\b(Red|red)\b/;
此模式匹配 Red 或 red 作为单个词。
〇 Red Rose
✕ reduce the workload
示例代码
用一个简单的例子来尝试。
let regexp = /\b(Red|red)\b/;
console.log(regexp.test('Red Rose'));
>> true
console.log(regexp.test('reduce the workload'));
>> false
console.log(regexp.test('Border color is red'));
>> true
console.log(regexp.test('predict a result'));
>> false
通过在正则表达式模式中设置捕获组,您可以将匹配部分模式的字符串与匹配整个模式的字符串分开。本节介绍如何在 JavaScript 正则表达式中使用捕获组。
设置捕获组并获取捕获
要在正则表达式模式中设置捕获组,请将要设置的部分括在括号 () 中。
/abc(def)ghi/
这里使用的括号与分组时指定的括号相同。用于分组的部分模式周围的括号也设置了捕获组。
例如,请参见下面的模式。
const regexp = /\d{3}-\d{4}/;
字符串 ‘zip code is 123-4567’ 匹配这个模式,匹配整个模式的字符串是 123-4567。这时设置一个捕获组,只获取模式中匹配\d{4}的部分。要设置捕获组,请将括号放在要设置的模式部分周围。
const regexp = /\d{3}-(\d{4})/;
现在,当字符串匹配模式时,我们得到匹配捕获组部分的 4567,除了匹配整个模式的字符串 123-4567。匹配捕获组的字符串称为捕获。
可以在一个模式中设置多个捕获组。
const regexp = /(\d{3})-(\d{4})/;
如果设置了多个捕获组,则从前面依次设置捕获组1、捕获组2等,然后通过指定捕获组的索引来引用捕获的字符串。
示例代码
用一个简单的例子来尝试。
let regexp = /(\d{3})-(\d{4})/;
let result = regexp.exec('邮编是 123-4567 。');
console.log(result[0]);
>> 123-4567
console.log(result[1]);
>> 123
console.log(result[2]);
>> 4567
设置不捕获的捕获组
即使分组括号在模式中括在括号 () 中时也会设置一个捕获组。如果不打算使用capture,也不想显式capture,可以设置一个不capture的capture group,写成下面的,而不是括号()。
(?:图案)
不要用“(”和“)”括起来,而是用“(?:”和“)”括起来。以这种格式包围与分组具有相同的功能,但不执行捕获。用于不打算捕获的组很方便,比如当你想通过迭代处理按顺序获取捕获组的值时。
示例代码
用一个简单的例子来尝试。
let regexp = /产品(?:Code|代码):([A-Z]{2})-(\d{2})/;
let result = regexp.exec('产品代码:AZ-07');
console.log(result[1]);
>> AZ
console.log(result[2]);
>> 07
本例中设置了三个捕获组,但是由于第一个捕获组设置了不捕获,所以按顺序捕获时,第二个捕获组和第三个捕获组都被捕获了。
使用命名捕获组
在 JavaScript 中,命名捕获组自 ECMAScript 2018 (ES 9) 起可用。您可以为每个捕获组设置一个名称,并使用名称而不是索引来引用捕获的值。格式如下。
(?<组名> 模式)
在普通的捕获组中,捕获组捕获的值是通过指定作为String对象的match方法的返回值得到的数组中的索引并引用元素的值来引用的。对于命名捕获组,你可以通过为你得到的数组指定一个名称作为匹配方法的返回值来引用捕获的值,就像这样:
数组.groups.组名
示例代码
用一个简单的例子来尝试。
let regexp = /产品代码:(?<section>[A-Z]{2})-(?<code>\d{2})/;
let result = regexp.exec('产品代码:ZH-82');
console.log(result.groups.section);
>> ZH
console.log(result.groups.code);
>> 82
与捕获值匹配相同值的模式
如果在模式中设置捕获组,则可以从同一模式中引用捕获组匹配的值,并编写模式以匹配与已捕获值相同的值。
引用时,在pattern中写\1引用capture 1的值,\2引用capture 2的值,以此类推
\捕捉号码
以下模式稍后引用第一个捕获组捕获的值。
const regexp = /(ABC).*\1/;
在这种情况下,模式以 ABC 开头,后跟任何字符零次或多次,然后是与第一个捕获组中捕获的值相同的值。第一个捕获组捕获的值是ABC,所以它和模式/ABC.*ABC/是一样的。
示例代码
用一个简单的例子来尝试。
const regex = /<(.+)>.*<\/\1>/;
let result = regex.exec('AAA <div>BBB<span>CCC</span>DDD</div>EEE');
console.log(result[0]);
>> <div>BBB<span>CCC</span>DDD</div>
在此示例中,我们匹配包含在结束标记(在本例中为 </div>)的字符串,其名称与找到的第一个标记(在本例中为 <div>)相同。我们稍后会引用捕获的值来查找具有相同名称的结束标记。
检查匹配时使用正则表达式中的先行和后行,但不将其作为匹配字符串检索。Lookahead有positive和negative lookahead,lookbehind有positive和negative lookahead。本节介绍如何使用 JavaScript 在正则表达式中使用先行和后行。
什么是正则表达式中的先行和后行
先行(正面前瞻、否定前瞻)和后视(正向后视、负向后视)の格式如下
模式A(?=模式B) 正面前瞻
模式A(?!模式B) 否定前瞻
(?<=模式B)模式A 正向后视
(?<!模式B)模式A 负向后视
Lookbehind 匹配模式 A 紧跟在模式 B 之后(或不匹配),而 lookbehind 匹配模式 A 紧接在模式 B 之前(或不匹配)。两者都判断是否存在包含模式 B 的匹配,但只获取与模式 A 匹配的部分作为匹配字符串。
让我们按顺序来看。
正面前瞻
如果主题字符串在模式 B 之后紧跟模式 A,则正先行匹配。此时,仅取得与模式A一致的部分作为一致值。
模式A(?=模式B) 正面前瞻
例如,考虑以下模式。
const regexp = /smart(?=phone)/;
仅匹配智能后跟电话。匹配智能手机,但不匹配智能或智能手表。只有聪明的人才能将其作为匹配的字符串获取。
示例代码
用一个简单的例子来尝试。
let regexp = /smart(?=phone)/;
console.log(regexp.test('smart'));
>> false
console.log(regexp.test('smartphone'));
>> true
console.log(regexp.test('smartwatch'));
>> false
let result = regexp.exec('smartphone');
console.log(result[0]);
>> smart
否定前瞻
如果目标字符串没有紧跟模式 B 的模式 A,则负先行匹配。此时,仅取得与模式A一致的部分作为一致值。
模式A(?!模式B) 否定前瞻
例如,考虑以下模式。
const regexp = /smart(?!phone)/;
仅当 smart 后跟的不是 phone 时才匹配。不匹配智能手机,但匹配智能和智能手表。只有聪明的人才能将其作为匹配的字符串获取。
示例代码
我会用一个简单的例子来尝试。
let regexp = /smart(?!phone)/;
console.log(regexp.test('smart'));
>> true
console.log(regexp.test('smartphone'));
>> false
console.log(regexp.test('smartwatch'));
>> true
let result = regexp.exec('smartwatch');
console.log(result[0]);
>> smart
正向后视
如果主题字符串在模式 A 之前具有模式 B,则正向后视匹配。此时,仅取得与模式A一致的部分作为一致值。
(?<=模式B)模式A 正向后视
例如,考虑以下模式。
const regexp = /(?<=digital)camera/;
仅当相机紧跟在数字之前时才匹配。它匹配 digitalcamera,但不匹配 camera 或 analogcamera。而且您只会将相机作为匹配的字符串。
示例代码
用一个简单的例子来尝试。
let regexp = /(?<=digital)camera/;
console.log(regexp.test('camera'));
>> false
console.log(regexp.test('digitalcamera'));
>> true
console.log(regexp.test('analogcamera'));
>> false
let result = regexp.exec('digitalcamera');
console.log(result[0]);
>> camera
负向后视
如果主题字符串中的模式 B 不在模式 A 之前,则负向后查找匹配。此时,仅取得与模式A一致的部分作为一致值。
(?<!模式B)模式A 负向后视
例如,考虑以下模式。
const regexp = /(?<!digital)camera/;
仅当 camera 前面没有紧跟 digital 时才匹配。不匹配 digitalcamera,但匹配 camera 和 analogcamera。而且您只会将相机作为匹配的字符串。
示例代码
用一个简单的例子来尝试。
let regexp = /(?<!digital)camera/;
console.log(regexp.test('camera'));
>> true
console.log(regexp.test('digitalcamera'));
>> false
console.log(regexp.test('analogcamera'));
>> true
let result = regexp.exec('analogcamera');
console.log(result[0]);
>> camera