RegExp.prototype.exec()

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

exec() 方法用於在指定字串中執行正則表示式搜尋匹配,並返回一個結果陣列,或者 null

試一試

const regex = /fo+/g;
const str = "table football, foosball";
let array;

while ((array = regex.exec(str)) !== null) {
  console.log(`Found ${array[0]}. Next starts at ${regex.lastIndex}.`);
  // Expected output: "Found foo. Next starts at 9."
  // Expected output: "Found foo. Next starts at 19."
}

語法

js
exec(str)

引數

str

要匹配的正則表示式的字串。所有值都會被 強制轉換為字串,因此省略它或傳遞 undefined 會導致 exec() 搜尋字串 "undefined",這通常不是你想要的。

返回值

如果匹配失敗,exec() 方法返回 null,並將正則表示式的 lastIndex 設定為 0

如果匹配成功,exec() 方法返回一個數組,並更新正則表示式物件的 lastIndex 屬性。返回的陣列將匹配的文字作為第一個元素,然後為匹配文字的每個捕獲組提供一個元素。陣列還具有以下附加屬性:

index

匹配在字串中的 0 索引。

input

用於匹配的原始字串。

groups

一個 null-prototype 物件,包含命名捕獲組,其鍵是名稱,值是捕獲組,如果沒有定義命名捕獲組,則值為 undefined。有關更多資訊,請參閱 捕獲組

indices 可選

僅當設定了 d 標誌時,才會出現此屬性。它是一個數組,其中每個條目代表一個子字串匹配的邊界。此陣列中每個元素的索引對應於 exec() 返回的陣列中相應子字串匹配的索引。換句話說,第一個 indices 條目代表整個匹配,第二個 indices 條目代表第一個捕獲組,依此類推。每個條目本身是一個包含兩個元素的陣列,第一個數字代表匹配的開始索引,第二個數字代表其結束索引。

indices 陣列還額外有一個 groups 屬性,其中包含所有命名捕獲組的 null-prototype 物件。鍵是捕獲組的名稱,每個值是一個包含兩個元素的陣列,第一個數字是開始索引,第二個數字是捕獲組的結束索引。如果正則表示式不包含任何命名捕獲組,則 groupsundefined

描述

當設定了 全域性粘性 標誌(例如,/foo/g/foo/y)時,JavaScript RegExp 物件是有狀態的。它們會儲存上一次匹配的 lastIndex。透過內部使用此屬性,exec() 可以用於迭代字串中的多個匹配(帶有捕獲組),而不是像 String.prototype.match() 那樣只獲取匹配的字串。

使用 exec() 時,如果設定了粘性標誌,全域性標誌將不起作用——匹配始終是粘性的。

exec() 是正則表示式的原生方法。許多其他正則表示式方法在內部呼叫 exec() — 包括字串方法呼叫的那些,例如 [Symbol.replace]()。雖然 exec() 本身功能強大(並且效率最高),但它通常不能最清晰地表達意圖。

  • 如果你只關心正則表示式是否匹配一個字串,而不關心實際匹配了什麼,請改用 RegExp.prototype.test()
  • 如果你正在查詢全域性正則表示式的所有匹配項,並且不關心捕獲組等資訊,請改用 String.prototype.match()。此外,String.prototype.matchAll() 可以透過允許你迭代匹配項來簡化匹配字串的多個部分(帶有捕獲組)。
  • 如果你執行匹配是為了在字串中找到其索引位置,請改用 String.prototype.search() 方法。

exec() 對於上面任何方法都難以實現的複雜操作很有用,通常在你需要手動調整 lastIndex 時。(String.prototype.matchAll() 會複製正則表示式,因此在迭代 matchAll 時更改 lastIndex 不會影響迭代。) 其中一個例子請參閱 重置 lastIndex

示例

使用 exec()

考慮以下示例

js
// Match "quick brown" followed by "jumps", ignoring characters in between
// Remember "brown" and "jumps"
// Ignore case
const re = /quick\s(?<color>brown).+?(jumps)/dgi;
const result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog");

下表顯示了執行此指令碼後的 result 狀態

屬性
[0] "Quick Brown Fox Jumps"
[1] "Brown"
[2] "Jumps"
index 4
indices [[4, 25], [10, 15], [20, 25]]
groups: { color: [10, 15 ]}
input "The Quick Brown Fox Jumps Over The Lazy Dog"
groups { color: "Brown" }

此外,re.lastIndex 將被設定為 25,因為這個正則表示式是全域性的。

查詢連續匹配項

如果你的正則表示式使用了 g 標誌,你可以多次使用 exec() 方法在同一個字串中查詢連續的匹配項。這樣做時,搜尋將從正則表示式的 lastIndex 屬性指定的 str 子字串開始(test() 也會推進 lastIndex 屬性)。請注意,在搜尋不同字串時,lastIndex 屬性不會被重置,它將從其當前 lastIndex 開始搜尋。

例如,假設你有以下指令碼

js
const myRe = /ab*/g;
const str = "abbcdefabh";
let myArray;
while ((myArray = myRe.exec(str)) !== null) {
  let msg = `Found ${myArray[0]}. `;
  msg += `Next match starts at ${myRe.lastIndex}`;
  console.log(msg);
}

此指令碼顯示以下文字

Found abb. Next match starts at 3
Found ab. Next match starts at 9

警告: 有許多陷阱可能導致這種情況變成無限迴圈!

  • 不要將正則表示式字面量(或 RegExp 建構函式)放在 while 條件內 — 它將在每次迭代時重新建立正則表示式並重置 lastIndex
  • 確保設定了 全域性 (g) 標誌,否則 lastIndex 將永遠不會被推進。
  • 如果正則表示式可能匹配零長度字元(例如,/^/gm),請每次手動增加其 lastIndex 以避免停留在同一位置。

你通常可以用 String.prototype.matchAll() 替換此類程式碼,使其更不容易出錯。

使用 exec() 和 RegExp 字面量

你也可以在不顯式建立 RegExp 物件的情況下使用 exec()

js
const matches = /(hello \S+)/.exec("This is a hello world!");
console.log(matches[1]);

這將記錄一條包含 'hello world!' 的訊息。

規範

規範
ECMAScript® 2026 語言規範
# sec-regexp.prototype.exec

瀏覽器相容性

另見