断言

断言包括边界,它们指示行和单词的开头和结尾,以及其他以某种方式指示匹配可能性的模式(包括前瞻、后顾和条件表达式)。

试一试

类型

边界类型断言

字符 含义
^

输入边界开始断言: 匹配输入的开头。如果启用了 multiline (m) 标志,则还匹配换行符之后的位置。例如,/^A/ 不匹配“an A”中的“A”,但匹配“An A”中的第一个“A”。

注意:此字符出现在 字符类 的开头时具有不同的含义。

$

输入边界结束断言: 匹配输入的结尾。如果启用了 multiline (m) 标志,则还匹配换行符之前的位置。例如,/t$/ 不匹配“eater”中的“t”,但匹配“eat”中的“t”。

\b

单词边界断言: 匹配单词边界。这是单词字符后面或前面不跟着另一个单词字符的位置,例如字母和空格之间。请注意,匹配的单词边界不包含在匹配结果中。换句话说,匹配的单词边界的长度为零。

示例

  • /\bm/ 匹配“moon”中的“m”。
  • /oo\b/ 不匹配“moon”中的“oo”,因为“oo”后面跟着“n”,它是一个单词字符。
  • /oon\b/ 匹配“moon”中的“oon”,因为“oon”是字符串的结尾,因此后面没有单词字符。
  • /\w\b\w/ 永远不会匹配任何内容,因为单词字符后面不可能同时跟着非单词字符和单词字符。

要匹配退格字符 ([\b]),请参阅 字符类

\B

非单词边界断言: 匹配非单词边界。这是前一个字符和下一个字符类型相同的位置:两者必须都是单词,或者两者必须都是非单词,例如两个字母之间或两个空格之间。字符串的开头和结尾被视为非单词。与匹配的单词边界相同,匹配的非单词边界也不包含在匹配结果中。例如,/\Bon/ 匹配“at noon”中的“on”,而 /ye\B/ 匹配“possibly yesterday”中的“ye”。

其他断言

注意:? 字符也可以用作量词。

字符 含义
x(?=y)

前瞻断言: 仅当“x”后面跟着“y”时才匹配“x”。例如,/Jack(?=Sprat)/ 仅当“Jack”后面跟着“Sprat”时才匹配“Jack”。
/Jack(?=Sprat|Frost)/ 仅当“Jack”后面跟着“Sprat”或“Frost”时才匹配“Jack”。但是,“Sprat”和“Frost”都不属于匹配结果的一部分。

x(?!y)

否定前瞻断言: 仅当“x”后面不跟着“y”时才匹配“x”。例如,/\d+(?!\.)/ 仅当数字后面不跟着小数点时才匹配该数字。/\d+(?!\.)/.exec('3.141') 匹配“141”,但不匹配“3”。

(?<=y)x

后顾断言: 仅当“x”前面有“y”时才匹配“x”。例如,/(?<=Jack)Sprat/ 仅当“Sprat”前面有“Jack”时才匹配“Sprat”。/(?<=Jack|Tom)Sprat/ 仅当“Sprat”前面有“Jack”或“Tom”时才匹配“Sprat”。但是,“Jack”和“Tom”都不属于匹配结果的一部分。

(?<!y)x

否定后顾断言: 仅当“x”前面没有“y”时才匹配“x”。例如,/(?<!-)\d+/ 仅当数字前面没有减号时才匹配该数字。/(?<!-)\d+/.exec('3') 匹配“3”。/(?<!-)\d+/.exec('-3') 匹配未找到,因为数字前面有减号。

示例

通用边界类型概述示例

js
// Using Regex boundaries to fix buggy string.
buggyMultiline = `tey, ihe light-greon apple
tangs on ihe greon traa`;

// 1) Use ^ to fix the matching at the beginning of the string, and right after newline.
buggyMultiline = buggyMultiline.replace(/^t/gim, "h");
console.log(1, buggyMultiline); // fix 'tey' => 'hey' and 'tangs' => 'hangs' but do not touch 'traa'.

// 2) Use $ to fix matching at the end of the text.
buggyMultiline = buggyMultiline.replace(/aa$/gim, "ee.");
console.log(2, buggyMultiline); // fix 'traa' => 'tree.'.

// 3) Use \b to match characters right on border between a word and a space.
buggyMultiline = buggyMultiline.replace(/\bi/gim, "t");
console.log(3, buggyMultiline); // fix 'ihe' => 'the' but do not touch 'light'.

// 4) Use \B to match characters inside borders of an entity.
fixedMultiline = buggyMultiline.replace(/\Bo/gim, "e");
console.log(4, fixedMultiline); // fix 'greon' => 'green' but do not touch 'on'.

使用 ^ 控制字符匹配输入的开头

使用 ^ 匹配输入的开头。在此示例中,我们可以通过 /^A/ 正则表达式获取以“A”开头的水果。为了选择合适的水果,我们可以使用带有 箭头 函数的 filter 方法。

js
const fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];

// Select fruits started with 'A' by /^A/ Regex.
// Here '^' control symbol used only in one role: Matching beginning of an input.

const fruitsStartsWithA = fruits.filter((fruit) => /^A/.test(fruit));
console.log(fruitsStartsWithA); // [ 'Apple', 'Avocado' ]

在第二个示例中,^ 用于匹配输入的开头,以及在 字符类 中使用时创建否定或补码字符类。

js
const fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];

// Selecting fruits that do not start by 'A' with a /^[^A]/ regex.
// In this example, two meanings of '^' control symbol are represented:
// 1) Matching beginning of the input
// 2) A negated or complemented character class: [^A]
// That is, it matches anything that is not enclosed in the square brackets.

const fruitsStartsWithNotA = fruits.filter((fruit) => /^[^A]/.test(fruit));

console.log(fruitsStartsWithNotA); // [ 'Watermelon', 'Orange', 'Strawberry' ]

输入边界断言 参考中查看更多示例。

匹配单词边界

在此示例中,我们匹配包含以“en”或“ed”结尾的单词的水果名称。

js
const fruitsWithDescription = ["Red apple", "Orange orange", "Green Avocado"];

// Select descriptions that contains 'en' or 'ed' words endings:
const enEdSelection = fruitsWithDescription.filter((descr) =>
  /(en|ed)\b/.test(descr),
);

console.log(enEdSelection); // [ 'Red apple', 'Green Avocado' ]

单词边界断言 参考中查看更多示例。

前瞻断言

在此示例中,我们仅当“First”后面跟着“test”时才匹配单词“First”,但我们不将“test”包含在匹配结果中。

js
const regex = /First(?= test)/g;

console.log("First test".match(regex)); // [ 'First' ]
console.log("First peach".match(regex)); // null
console.log("This is a First test in a year.".match(regex)); // [ 'First' ]
console.log("This is a First peach in a month.".match(regex)); // null

前瞻断言 参考中查看更多示例。

基本否定前瞻断言

例如,/\d+(?!\.)/ 仅当数字后面不跟着小数点时才匹配该数字。/\d+(?!\.)/.exec('3.141') 匹配“141”,但不匹配“3.”。

js
console.log(/\d+(?!\.)/g.exec("3.141")); // [ '141', index: 2, input: '3.141' ]

前瞻断言 参考中查看更多示例。

“?!“组合在断言和字符类中的不同含义

?! 组合在断言(如 /x(?!y)/)和 字符类(如 [^?!])中具有不同的含义。

js
const orangeNotLemon =
  "Do you want to have an orange? Yes, I do not want to have a lemon!";

// Different meaning of '?!' combination usage in Assertions /x(?!y)/ and Ranges /[^?!]/
const selectNotLemonRegex = /[^?!]+have(?! a lemon)[^?!]+[?!]/gi;
console.log(orangeNotLemon.match(selectNotLemonRegex)); // [ 'Do you want to have an orange?' ]

const selectNotOrangeRegex = /[^?!]+have(?! an orange)[^?!]+[?!]/gi;
console.log(orangeNotLemon.match(selectNotOrangeRegex)); // [ ' Yes, I do not want to have a lemon!' ]

后顾断言

在此示例中,我们仅当“orange”前面有“ripe”时才将其替换为“apple”。

js
const oranges = ["ripe orange A", "green orange B", "ripe orange C"];

const newFruits = oranges.map((fruit) =>
  fruit.replace(/(?<=ripe )orange/, "apple"),
);
console.log(newFruits); // ['ripe apple A', 'green orange B', 'ripe apple C']

后顾断言 参考中查看更多示例。

另请参阅