深入探索 JavaScript 中的 RegExp:創建動態規則運算式
更新日期: 2024 年 9 月 14 日
JavaScript 的 new RegExp 功能允許開發者在程式運行時,才決定如何搜尋或匹配文本。
特別適合於當你事前不確定要搜尋的文本內容,或需要根據使用者的輸入,來確定搜尋條件的情況。
簡單來說,就是可以讓你根據實際需要,隨時自定義搜尋規則。
new RegExp 的語法
new RegExp 方法接受兩個參數:pattern(模式) 與 flags(修飾符)。
其基本語法如下:
let regex = new RegExp(pattern, flags);
pattern(模式)
當你用 new RegExp 創建規則運算式時,「pattern(模式)」就像是你給搜尋引擎的一張搜尋清單,告訴它你想找的文字長什麼樣子。
這個模式可以是具體的文字,比如你告訴它我要找「貓」,也可以是比較含糊的指令,比如找所有的電話號碼或電子郵件地址。
想像一下,你在一本書里找某個詞,「pattern」就是那個詞。
但是,規則運算式的厲害之處在於,它可以不只找一個確切的詞,還可以根據你定義的模式找到一系列符合某種特徵的文字。
比如,你可以告訴它,我要找所有以「貓」開頭,後面跟著三個字的詞,或者找所有的「貓」和「狗」。
在這個「pattern」裡面,你可以用一些特殊的符號來幫助描述你想找的東西。例如:
直接字符
就是直接告訴搜尋引擎你要找的字,比如你告訴它我要找「apple」,那它就會去找所有「apple」的字眼。
特殊字符
這些是一些有特殊意涵的符號,它們可以幫你找到更多不同的東西。比如:
.
符號:可以代表任何一個字母或數字,想象一下你在問:「有沒有任何字母或數字在這裡?」*
符號:是用來找某個東西出現了多次的,甚至是零次,好像在說:「這個東西可能一次都沒有,也可能一堆。」+
符號:則是至少要有一次,就是:「這個東西至少要出現一次,多了也沒關係。」
字符類
這個像是你給搜尋引擎一個選擇題,比如[abc]就是說:我要找「a」、「b」、或者「c」,三選一。
量詞
這個可以指定你要找的東西出現的次數,像是{2,3}就是在問:這個東西出現 2 次或 3 次的有嗎?
位置匹配
有時候你對在哪裡找到的東西很在意,比如:
- ^ 符號:是說我只在乎開頭的部分,如果開頭符合我就要。
- $ 符號:則是我只在乎結尾的部分,結尾對了就行。
用這些技巧,你可以讓規則運算式變成一個超級精確的搜尋工具,幫你找到需要的任何文字信息。
flags(修飾符)
當你用 new RegExp 來創建規則運算式時,除了告訴它要找的模式外,你還可以選擇加一些特別的「提示」來幫助它更好地找到你要的東西,這就是所謂的「flags(修飾符)」。
這些「提示」可以讓搜尋變得更靈活,以下是幾個常見的提示:
- g:通常,找到一個符合條件的就會停止搜尋。加上這個 g,就像是告訴它「全場都搜一遍,找到所有符合的地方」。
- i:有時候我們不在乎大小寫,比如「Apple」和「apple」對我們來說是一樣的。這時候加上「i」,就是告訴它大寫、小寫都一視同仁,你不用區分。
- s:通常情況下,
.
(點)這個特殊字符用於匹配除換行符(\n
)之外的任意單個字符。但有時候,我們希望連換行符也包括在內,使得.
能匹配任何字符,包括換行符。 - m:如果你的文字是分成多行的,通常情況下搜尋是看成一整塊文字的。加上 m,就像是告訴它「每一行都是獨立的,分開來看」。
- u:有時候文字中會有特殊的國際字元或表情符號,用 u 就是告訴它這些特殊的字元也要正確處理。
- y:這個有點像是遊戲中的「必須從這裡開始」的限制。加上 y,就是告訴它「你只能從我指定的地方開始找,不能隨便找」。
這些「提示」就像是給搜尋引擎的便利貼,幫助它更好地按照你的要求去找資料。根據你想要如何搜尋,選擇合適的修飾符,就能讓你的搜尋更加精準。
回傳值
使用 new RegExp 會返回一個規則運算式物件。
這個物件裡面包含了你設定的搜尋模式(也就是你想要搜尋的規則,比如某個詞或者字符序列),以及任何你加上的修飾符(比如是否忽略大小寫,或者搜尋全文等等)。
這個規則運算式物件可以用在很多字符串(string)方法中,幫助你處理文本。
以下是一些回傳物件的相關方法:
.test()
如果你只想檢查文本中是否存在符合規則運算式的部分,可以使用 .test() 方法。
這個方法會返回一個布林值(true 或 false),告訴你文本是否匹配你的搜尋條件。
let pattern = new RegExp('apple', 'i');
let text = "Do you like apples?";
let hasApple = pattern.test(text);
console.log(hasApple);
// 輸出:
// true
.exec()
這個方法接受一個文字參數,並根據規則運算式在該參數文字中搜尋。
每次只返回一個匹配結果的陣列資訊(包括匹配的文本、索引等),如果你想要找到所有匹配項,需要多次調用 .exec()。
如果沒有匹配到就返回 null。
let pattern = new RegExp('apple', 'gi');
let text = "Apples are green, and apples are sweet.";
let match;
console.log(pattern.exec(text));
console.log(pattern.exec(text));
// 回傳:
// [
// 'Apple',
// index: 0,
// input: 'Apples are green, and apples are sweet.',
// groups: undefined
// ]
// [
// 'apple',
// index: 22,
// input: 'Apples are green, and apples are sweet.',
// groups: undefined
// ]
new RegExp 與字面量語法的差異
字面量語法
這就像是直接在代碼裡寫下你的搜尋規則,用兩個斜杠包起來,比如:
let regex = /abc/ ;
這種方式簡單直觀,你寫的時候就確定了要搜尋的模式,而且這種方法創建的規則運算式效率更高,因為它在腳本加載時就已經準備好了。
new RegExp
這是一個函數,可以動態地創建規則運算式。
你如果不確定搜尋的模式,想要在運行時根據某些條件來決定,那就用此函數。
let userInput = 'abc';
let regex = new RegExp(userInput);
比如你想根據用戶的輸入來建立一個搜尋模式,就可以先拿到用戶輸入的字符串,然後用 new RegExp(userInput) 這樣的方式來創建。
這種方法靈活,但是相對來說效率不如字面量語法,因為它是在程式運行時才創建的。
主要差異
兩者的主要差異就在於:
- 確定性:字面量語法在寫代碼的時候就確定了,而 new RegExp 可以在程式運行時根據情況來動態創建。
- 效率:字面量因為在加載時就已經準備好,所以效率較高;new RegExp 則在需要的時候才創建,效率略低。
- 靈活性:如果你需要根據不同情況改變搜尋模式,new RegExp 更加靈活。
使用 new RegExp 的場景
new RegExp 的主要優勢在於其動態性。
以下示例展示了如何使用 new RegExp 根據用戶輸入動態生成規則運算式:
// 假設用戶輸入了一個搜索關鍵字
let userInput = "JavaScript";
// 動態創建一個不區分大小寫的搜索規則運算式
let regex = new RegExp(userInput, "i");
// 使用這個規則運算式來搜尋文本
let text = "JavaScript is a programming language.";
let matchResult = text.match(regex);
console.log(matchResult);
// 輸出:
// ['JavaScript']
延伸閱讀:JavaScript match() 方法:如何輕鬆處理字串匹配
實際應用範例
表單驗證
在網頁應用中,表單驗證是保證用戶輸入數據有效性的關鍵步驟。
利用規則運算式,我們可以實現各種輸入格式的驗證,如電子郵件地址、手機號碼等。
// 驗證電子郵件地址
function validateEmail(email) {
let emailRegex = new RegExp("^\\S+@\\S+\\.\\S+$");
return emailRegex.test(email);
}
console.log(validateEmail("example@example.com"));
// 輸出:
// true
console.log(validateEmail("invalid-email"));
// 輸出:
// false
在這個範例中,我們使用了 new RegExp 來創建一個簡單的電子郵件驗證規則運算式。
檢查輸入是否包含基本的電子郵件格式:一個 “@” 符號和至少一個點。
字符串搜尋和替換
規則運算式在處理文本數據時特別有用,尤其是在需要搜尋和替換特定模式的字符串時。
// 替換文本中的特定字詞
function censorText(text, forbiddenWordsArray) {
let pattern = forbiddenWordsArray.join("|");
let regex = new RegExp(pattern, "gi");
return text.replace(regex, "****");
}
let result = censorText("This is a secret and confidential document.", ["secret", "confidential"]);
console.log(result); // 輸出:"This is a **** and **** document."
這個範例展示了如何使用 new RegExp 來動態創建一個規則運算式,該規則運算式匹配一組禁用詞並將它們替換為 “****”,達到檢查文本並隱藏敏感資訊的目的。
從文本中提取信息
規則運算式也非常適合於從文本中提取特定格式的信息,例如提取日期、URL、電話號碼等。
// 提取文本中的所有URL
function extractUrls(text) {
let urlRegex = new RegExp("(https?:\/\/[^\s]+)", "gi");
return text.match(urlRegex) || [];
}
let text = "Visit our website at https://example.com or our blog at http://blog.example.com.";
let urls = extractUrls(text);
console.log(urls);
// 輸出:
// ["https://example.com", "http://blog.example.com"]
在這個範例中,我們定義了一個用於匹配 HTTP 和 HTTPS URL 的規則運算式,並通過 match 方法從一段文本中提取所有符合條件的 URL。
結論
在本文中,我們深入探討了 new RegExp 在 JavaScript 中的應用,從基礎概念到進階技巧,再到實際應用範例。
希望幫助你在撰寫代碼時更容易理解、發揮出它的最大價值。