百度工程師帶你玩轉正則

語言: CN / TW / HK

自定義模板-3.jpg

作者 | 向陽

導讀

在很多技術領域,都有正則的身影。但許多像我一樣的人,只聞其名。因此將正則常用知識彙總,便於查閲。正則表達式(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 分組的目的

  1. 作為可選分支

  2. 簡寫重複模式

  3. 緩存捕獲數據及反向引用(只有捕獲組才可以被反向引用)

4.2 捕獲組

當你把一個正則表達式用一對小括號包起來的時候,就形成了一個捕獲組。它捕獲的就是分組裏面的正則表達式匹配到的內容。

/(\w)+/.test('hello world') //(\w)組成一個捕獲組

4.3 非捕獲組

/(?:\w)+/.test('hello world') //(\w)組成一個捕獲組

使用場景:

不需要用到分組裏面的內容的時候,用非捕獲組,主要是為了提升效率,因為捕獲組多了一步保存數據的步驟,所以一般會多耗費一些時間。

4.4 命名捕獲組

捕獲組其實是分為編號捕獲組Numbered Caputuring Groups和命名捕獲組Named Capturing Groups的,我們上面説的捕獲組,默認指的是編號捕獲組。命名捕獲組,也是捕獲組,只是語法不一樣。命名捕獲組的語法如下:(?group) 或 (?'name'group),其中 name 表示捕獲組的名稱,group 表示捕獲組裏面的正則。

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]菜鳥教程:

https://www.runoob.com/regexp/regexp-intro.html

[2]MDN:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test

推薦閲讀:

Diffie-Hellman密鑰協商算法探究

貼吧低代碼高性能規則引擎設計

淺談權限系統在多利熊業務應用

分佈式系統關鍵路徑延遲分析實踐

百度工程師教你玩轉設計模式(裝飾器模式)

百度工程師帶你體驗引擎中的nodejs