非捕獲組:(?:...)
非捕獲組將子模式分組,允許你對整個組應用量詞,或在其中使用或運算子。它的作用類似於 JavaScript 表示式中的分組運算子,與捕獲組不同,它不記住匹配的文字,從而提供更好的效能,並避免當模式中也包含有用的捕獲組時造成的混淆。
語法
正則表示式
(?:pattern)
引數
示例
將子模式分組並應用量詞
在以下示例中,我們測試檔案路徑是否以 styles.css 或 styles.[a hex hash].css 結尾。由於整個 \.[\da-f]+ 部分是可選的,為了對其應用 ? 量詞,我們需要將其分組到一個新的原子中。使用非捕獲組透過不建立我們不需要的額外匹配資訊來提高效能。
js
function isStylesheet(path) {
return /styles(?:\.[\da-f]+)?\.css$/.test(path);
}
isStylesheet("styles.css"); // true
isStylesheet("styles.1234.css"); // true
isStylesheet("styles.cafe.css"); // true
isStylesheet("styles.1234.min.css"); // false
分組或運算子
或運算子在正則表示式中具有最低的優先順序。如果你想將或運算子作為更大模式的一部分使用,你必須將其分組。除非你依賴於或運算子匹配的文字,否則建議使用非捕獲組。以下示例使用與輸入邊界斷言文章相同的程式碼來匹配副檔名
js
function isImage(filename) {
return /\.(?:png|jpe?g|webp|avif|gif)$/i.test(filename);
}
isImage("image.png"); // true
isImage("image.jpg"); // true
isImage("image.pdf"); // false
避免重構風險
捕獲組透過它們在模式中的位置訪問。如果你新增或刪除捕獲組,則必須更新其他捕獲組的位置,如果你透過匹配結果或反向引用訪問它們。這可能是錯誤的來源,特別是如果大多陣列純粹用於語法目的(應用量詞或分組或運算子)。使用非捕獲組可以避免此問題,並允許輕鬆跟蹤實際捕獲組的索引。
例如,假設我們有一個函式,用於匹配字串中的 title='xxx' 模式(示例取自捕獲組)。為了確保引號匹配,我們使用反向引用來引用第一個引號。
js
function parseTitle(metastring) {
return metastring.match(/title=(["'])(.*?)\1/)[2];
}
parseTitle('title="foo"'); // 'foo'
如果我們後來決定新增 name='xxx' 作為 title= 的別名,我們將需要將或運算子分組到另一個組中
js
function parseTitle(metastring) {
// Oops — the backreference and index access are now off by one!
return metastring.match(/(title|name)=(["'])(.*?)\1/)[2];
}
parseTitle('name="foo"'); // Cannot read properties of null (reading '2')
// Because \1 now refers to the "name" string, which isn't found at the end.
與其定位所有引用捕獲組索引的地方並逐一更新它們,不如避免使用捕獲組
js
function parseTitle(metastring) {
// Do not capture the title|name disjunction
// because we don't use its value
return metastring.match(/(?:title|name)=(["'])(.*?)\1/)[2];
}
parseTitle('name="foo"'); // 'foo'
命名捕獲組是避免重構風險的另一種方式。它允許透過自定義名稱訪問捕獲組,當其他捕獲組新增或刪除時,該名稱不受影響。
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # prod-Atom |
瀏覽器相容性
載入中…