完全解析:JavaScript 的 matchAll() 函數如何改變字串搜索遊戲

更新日期: 2024 年 3 月 4 日

本文將從 matchAll() 函數的基本介紹開始,逐步深入到其在實際應用中的多樣化用法。

藉由深入解析和實際示例,我們將展示 matchAll() 是如何徹底改變文字搜索遊戲規則,並探討它如何使得處理複雜文本數據變得更加簡單和高效。

無論你是一名 JavaScript 新手,還是一位經驗豐富的開發者,了解 matchAll() 函數都將為你的工具箱增添一項強大的工具。

閱讀建議

若希望更好的理解本文描述的內容,建議先理解以下兩個相關概念,才便於熟悉接下來討論的觀念:

matchAll() 函數概述

JavaScript 的 matchAll() 函數,是一個強大的字串處理工具。它允許開發者找到一個字串中所有匹配規則運算式的結果。

不同於 match() 函數僅返回第一個匹配成交的字串,matchAll() 返回一個包含所有匹配結果的「迭代器」。

每個匹配結果都是一個包含「匹配字串」及其「捕獲組」的陣列。

基本用法

要使用 matchAll() 函數,首先需要一個規則運算式,並且該規則運算式應使用全局標誌(g),這樣才能返回所有匹配項,而不是停在第一個匹配。

下面是一個基本的例子:

const text = "The rain in Spain stays mainly in the pplain";
const regex = /ain/g;
const matches = text.matchAll(regex);

for(const match of matches){
  console.log(match);
}

// 回傳:

// [
//   'ain',
//   index: 5,
//   input: 'The rain in Spain stays mainly in the pplain',
//   groups: undefined
// ]

// [
//   'ain',
//   index: 14,
//   input: 'The rain in Spain stays mainly in the pplain',
//   groups: undefined
// ]

// [
//   'ain',
//   index: 25,
//   input: 'The rain in Spain stays mainly in the pplain',
//   groups: undefined
// ]

// [
//   'ain',
//   index: 41,
//   input: 'The rain in Spain stays mainly in the pplain',
//   groups: undefined
// ]

這段代碼會找出 text 字符串中所有含有 “ain” 的部分,並且逐一輸出。

與 match() 的比較

相比於 match() 函數,matchAll() 的一大優勢是其返回的迭代器,使得處理多個匹配結果變得非常方便。

而 match() 在使用全局標誌時只返回匹配的字符串,而不包括捕獲組或匹配的索引。

matchAll() 則提供了一個更豐富的資料包,包括每次匹配的完整細節。

返回值

matchAll() 返回的是一個迭代器,這意味著你可以使用 for…of 循環、展開操作符(...)或者 Array.from() 方法來操作這些匹配結果。

每個迭代的元素都是一個代表匹配結果的陣列,陣列中第一個數據是匹配的完整文字,後續額外資訊為是任何捕獲的組。

陣列還包括了匹配在原始字符串中的位置和輸入的原始字符串。

實際應用場景

JavaScript 的 matchAll() 函數不僅僅是一種文本搜索的工具,它在多種場景下都展現出了極大的應用價值。

透過下面的例子,我們將探索 matchAll() 在實際開發中的幾種用途。

基本字符串匹配

在日常開發中,我們經常需要從文本中擷取信息。matchAll() 使這一過程變得簡單而高效。

例如,從一段文本中擷取所有電子郵件地址:

// 這行代碼定義了一個字符串 text,其中包含一段文本。
// 這段文本包括兩個電子郵件地址:support@example.com 和 sales@example.com。
const text = "Contact us at support@example.com or sales@example.com.";

// 這行代碼創建了一個規則運算式 emailRegex,用於匹配文本中的電子郵件地址。
const emailRegex = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g;

// Array.from() 將這個迭代器轉換成一個陣列
// 同時使用箭頭函數 m => m[0] 擷取每個匹配結果的第一個元素(即完整的匹配文本,也就是電子郵件地址本身)
const emails = Array.from(text.matchAll(emailRegex), element => element[0]);

console.log(emails); 

// 回傳:
// ["support@example.com", "sales@example.com"]

這個例子演示了如何利用 matchAll() 和規則運算式快速擷取文本中的所有電子郵件地址。

補充:Array.from 函數介紹

Array.from() 是一個 JavaScript 中的方法,屬於 Array 類。它的主要功能是創建一個新的陣列。

你可以用它來把那些看起來像陣列但不是真正陣列的東西,或者是可以一步步遍歷的物件(比如列表或範圍),轉換成真正的陣列。這樣做之後,你就能在這些原本不是陣列的東西上使用陣列的所有功能了。

簡單來說,Array.from() 讓你能夠輕鬆地把各種集合轉換成真正的陣列,這對於處理數據和使用陣列的方法非常有幫助。

基本語法:

Array.from(arrayLike, mapFn, thisArg)
  • arrayLike:這是一個類陣列對象或可迭代對象,是 Array.from() 方法的第一個且必須提供的參數。這個參數指定了想要轉換成陣列的對象。
  • mapFn(可選):這是一個函數,如果提供,新陣列中的每個元素會在加入陣列之前先通過這個函數進行處理。這個參數是可選的。
  • thisArg(可選):當提供 mapFn 函數時,thisArg 可用於指定 mapFn 函數內 this 的值。這個參數也是可選的。

延伸閱讀:從零開始:JavaScript Map 函數新手指南

捕獲組和分組匹配

matchAll() 對於處理包含捕獲組的複雜匹配模式特別有用。

例如,從一段文本中擷取所有日期,並將其分解為年、月、日:

const text = "Important dates: 1992-04-02, 2023-12-25.";
const dateRegex = /(\d{4})-(\d{2})-(\d{2})/g;
const dates = Array.from(text.matchAll(dateRegex), element => ({
  year: element[1],
  month: element[2],
  day: element[3],
}));

console.log(dates); 

// 回傳
// [
//     { year: '1992', month: '04', day: '02' },
//     { year: '2023', month: '12', day: '25' }
// ]

這個例子顯示了如何利用捕獲組從匹配結果中擷取特定資訊。

錯誤日誌分析

對於需要分析大量日誌數據的應用,matchAll() 可以用來搜索特定模式的日誌條目。

例如,找出所有錯誤消息:

const logs = `INFO: User logged in.
              ERROR: Database connection failed.
              INFO: Data retrieved successfully.`;

const errorRegex = /^ERROR: (.*)$/gm;

const errors = Array.from(logs.matchAll(errorRegex), element => element[1]);

console.log(errors); // ["Database connection failed."]

這段代碼示範了如何使用 matchAll() 搭配多行模式標誌(m)從日誌中擷取錯誤訊息。

注意事項

雖然 matchAll() 函數為文本處理提供了強大的能力,但在使用時也有一些重要的注意事項和最佳實踐需要遵守,以確保效率和避免常見的陷阱。

確保使用全局標誌

matchAll() 函數要求規則運算式帶有全局標誌(g),這是因為它旨在返回所有匹配的結果。

如果忘記添加全局標誌,將會導致 matchAll() 拋出一個錯誤。

因此,始終確保你的規則運算式使用了正確的標誌:

// 正確
const regex = /pattern/g;

// 錯誤
const regex = /pattern/;

處理返回的迭代器

由於 matchAll() 返回的是一個迭代器,因此需要使用迭代器相關的操作來處理匹配結果。

你可以使用 for…of 循環、展開操作符(…)或 Array.from() 來迭代或轉換結果。

了解如何有效地操作這些迭代器對於充分利用 matchAll() 返回的數據至關重要。

注意記憶體使用

雖然迭代器模式通常更高效,但在處理大型文本或大量數據時,仍需注意記憶體使用。

避免一次性將所有結果轉換為陣列,尤其是在不確定匹配數量時。

按需處理每個匹配項可以幫助管理記憶體負擔,提高應用性能。

利用捕獲組

當你的規則運算式包含捕獲組時,matchAll() 會在每個匹配結果中提供這些組的詳細信息。

有效地利用這些捕獲組可以讓你從文本中擷取更加豐富的資訊。

熟悉規則運算式的捕獲組語法和應用將大大增強你利用 matchAll() 進行數據擷取的能力。

測試和驗證

由於正則表達式可能非常複雜,並且對於特定的模式可能有多種實現方式,因此在將 matchAll() 應用於生產環境前,進行充分的測試和驗證是必要的。

使用各種測試字符串來確保你的正則表達式正確無誤,並按預期返回所有匹配結果。

結語

本文通過介紹 matchAll() 函數的基本用法、實際應用場景、以及如何有效利用其特性來改善文本搜索和處理,旨在幫助讀者理解和掌握這一工具。

從基本的字符串匹配到複雜的數據擷取,matchAll() 函數都證明了自己在各種情境下的價值和效率。

Similar Posts