斷言

斷言包括邊界,它們指示行和單詞的開始和結束,以及以某種方式指示可能匹配的其他模式(包括先行斷言、後行斷言和條件表示式)。

試一試

const text = "A quick fox";

const regexpLastWord = /\w+$/;
console.log(text.match(regexpLastWord));
// Expected output: Array ["fox"]

const regexpWords = /\b\w+\b/g;
console.log(text.match(regexpWords));
// Expected output: Array ["A", "quick", "fox"]

const regexpFoxQuality = /\w+(?= fox)/;
console.log(text.match(regexpFoxQuality));
// Expected output: Array ["quick"]

型別

邊界型斷言

字元 含義
^

輸入邊界起始斷言: 匹配輸入的開頭。如果啟用了 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((description) =>
  /(?:en|ed)\b/.test(description),
);

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

請參閱單詞邊界斷言參考中的更多示例。

先行斷言

在此示例中,我們只匹配單詞“First”,前提是它後面跟著單詞“test”,但我們不將“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']

請參閱後行斷言參考中的更多示例。

另見