百度工程師帶你玩轉正則
作者 | 向陽
導讀
在很多技術領域,都有正則的身影。但許多像我一樣的人,只聞其名。因此將正則常用知識彙總,便於查閱。正則表示式(Regular Expression)是用於描述一組字串特徵的模式,用來匹配特定的字串。通過特殊字元+普通字元來進行模式描述,從而達到文字匹配目的工具。因此正則表示式是用於匹配字串中字元組合的模式。
正則表示式可以很方便的提取我們想要的資訊,所以正則表示式是一個很重要的知識點!歡迎大家一起學習~
全文4082字,預計閱讀時間11分鐘。
01 正則概述
正則表示式是用於匹配字串中字元組合的模式。在 JavaScript中,正則表示式也是物件。
02 基本語法
2.1 定義方式
字面量方式:/^\d+$/g,
new RegExp("^\\d+$", "g")
2.2 修飾符
2.3 元字元
一個正則表示式模式是由簡單的字元所構成的,比如 /abc/;或者是簡單和特殊字元的組合,比如 /ab*c/
2.4 其他斷言
斷言的組成之一是邊界。對於文字、詞或模式,邊界可以用來表明它們的起始或終止部分,分為邊界類斷言與其他斷言。邊界類斷言有 ^, $, \b, \B,其他斷言有 x(?=y), x(?!y), (?<=y)x, (?<!y)x。
注:需要關注寫法與真正匹配到的字串!!!
03 正則物件的屬性和方法
3.1 屬性
△正則屬性和方法
var reg=/ab/g;
reg.ignoreCase; // false,檢測是否含有i 屬性
reg.global; // true,檢測是否含有g 屬性
reg.multiline; // false,檢測是否含有m 屬性
reg.source; // "ab",匹配內容體
var regex =new RegExp("\u{61}","u");
regex.unicode // true
const str1 = "foo bar foo";
const regex1 = /foo/dg;
regex1.hasIndices // Output: true
regex1.exec(str1).indices[0] // Output: Array [0, 3]
regex1.exec(str1).indices[0] // Output: Array [8, 11]
const str2 = "foo bar foo";
const regex2 = /foo/;
regex2.hasIndices // Output: false
regex2.exec(str2).indices // Output: undefined
3.2 相關方法
這些模式被用於RegExp的exec和test方法,以及String的match、matchAll、replace、search和split方法。
test
/str/.test('hello world'); //要求字串包含string,所以返回false
exec
``` var reg=/ab/g; var str="abababab"; reg.lastIndex //0 reg.exec(str)//["ab",index:0,input:"abababab"] reg.lastIndex//2 reg.exec(str)//["ab",index:2,input:"abababab"] reg.lastIndex//4 reg.exec(str)//["ab",index:4,input:"abababab"] reg.lastIndex//6 reg.exec(str)//["ab",index:6,input:"abababab"] reg.lastIndex//8 reg.exec(str)//null reg.lastIndex//0 reg.exec(str)//["ab",index:0,input:"abababab"]
//reg.lastIndex是可手動修改的 reg.lastIndex=0; // reg.lastIndex重置0 reg.exec(str) // ["ab",index:0,input:"abababab"],與上面結果中的index相同
// 若匹配規則不含有global屬性,那在允許exec()方法後lastIndex值始終為0 var reg=/ab/; var str="abababab"; reg.lastIndex // 0 reg.exec(str) // ["ab",index:0,input:"abababab"] reg.lastIndex // 0 reg.exec(str) // ["ab",index:0,input:"abababab"] ```
search
"hello world".search(/w/) // 6
match
const str = "hello world";
const reg1 = /o/;
str.match(reg1); // ['o', index: 4, input: 'hello world', groups: undefined]
const reg2 = /o/g;
str.match(reg2); // ['o', 'o']
replace
"hello world".replace(/world/g,"baidu"); // hello baidu
split
var str="a1b2c";
var reg=/\d/g;
str.split(reg); // ["a","b","c"],即將分隔符兩側的字串進行拆分
var reg=/(\d)/g; // "()"代表記錄反向引用,將匹配表示式也返回回來
str.split(reg); // ["a","1","b","2","c"]
04 捕獲組與非捕獲組
正則表示式分組分為捕獲組(Capturing Groups)與非捕獲組Non-Capturing Groups。正則裡面是用成對的小括號來表示分組的,如(\d)表示一個分組,(\d)(\d)表示有兩個分組,(\d)(\d)(\d)表示有三個分組,有幾對小括號元字元組成,就表示有幾個分組。
4.1 分組的目的
-
作為可選分支
-
簡寫重複模式
-
快取捕獲資料及反向引用(只有捕獲組才可以被反向引用)
4.2 捕獲組
當你把一個正則表示式用一對小括號包起來的時候,就形成了一個捕獲組。它捕獲的就是分組裡面的正則表示式匹配到的內容。
/(\w)+/.test('hello world') //(\w)組成一個捕獲組
4.3 非捕獲組
/(?:\w)+/.test('hello world') //(\w)組成一個捕獲組
使用場景:
不需要用到分組裡面的內容的時候,用非捕獲組,主要是為了提升效率,因為捕獲組多了一步儲存資料的步驟,所以一般會多耗費一些時間。
4.4 命名捕獲組
捕獲組其實是分為編號捕獲組Numbered Caputuring Groups和命名捕獲組Named Capturing Groups的,我們上面說的捕獲組,預設指的是編號捕獲組。命名捕獲組,也是捕獲組,只是語法不一樣。命名捕獲組的語法如下:(?
const str = '2022-12-15';
const reg = /(\d{4})-(\d{2})-(\d{2})/;
str.match(reg)
// ['2022-12-15', '2022', '12', '15', index: 0, input: '2022-12-15', groups: undefined]
const isNotCaputuringReg = /(?:\d{4})-(?:\d{2})-(?:\d{2})/;
str.match(isNotCaputuringReg)
// ['2022-12-15', index: 0, input: '2022-12-15', groups: undefined]
const namedCaputuringReg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
str.match(namedCaputuringReg)
// 匹配結果如下圖
05 正則中有趣用法
5.1 貪婪匹配與非貪婪匹配
貪婪匹配即照著"量詞"規則中要求的更多個的情況去做匹配。
非貪婪匹配,在"量詞"規則後邊多加一個問號"?"。
"量詞"包括 ?、*、+、{}、{n,}、{n,m}
var str="aaaaa";
var reg=/a+/g;
str.match(reg);//["aaaaa"]
var reg=/a??/g;//第一個問號代表0~1個,第二個問號代表能取0就不取1去做匹配
str.match(reg);//["","","","","",""]
5.2 反向引用
反向引用就是正則中' \1 '用法,下列程式碼中(\w)首先匹配a,'\1'引用a,後面量詞'+'表示出現一次獲多次。
var str = 'aaaaabbbbbbcccccccd'
var reg = /(\w)\1+/g
str.replace(reg,'$1') // $1是第一個小括號中的內容
// abc
06 易錯用法
/[1-51]/.test('6')
'aaa'.match(/a*?/g)
false // 可匹配1,2,3,4,5,同(1-5||1)
['', '', '', ''] //注意:字串有三個a,陣列有四個空字串
——END——
參考資料:
[1]菜鳥教程:
http://www.runoob.com/regexp/regexp-intro.html
[2]MDN:
http://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
推薦閱讀:
- 精準水位在流批一體資料倉庫的探索和實踐
- 視訊編輯場景下的文字模版技術方案
- 淺談活動場景下的圖演算法在反作弊應用
- 百度工程師帶你玩轉正則
- Serverless:基於個性化服務畫像的彈性伸縮實踐
- 百度APP iOS端記憶體優化-原理篇
- 從稀疏表徵出發、召回方向的前沿探索
- 效能平臺數據提速之路
- 採編式AIGC視訊生產流程編排實踐
- 百度工程師漫談視訊理解
- PGLBox 超大規模 GPU 端對端圖學習訓練框架正式釋出
- 百度工程師淺談分散式日誌
- 百度工程師帶你瞭解Module Federation
- 巧用Golang泛型,簡化程式碼編寫
- Go語言DDD實戰初級篇
- 百度工程師帶你玩轉正則
- Diffie-Hellman金鑰協商演算法探究
- 貼吧低程式碼高效能規則引擎設計
- 淺談許可權系統在多利熊業務應用
- 分散式系統關鍵路徑延遲分析實踐