深入學習正規表示式

2021-09-24 07:37:30 字數 4302 閱讀 4235

分組:正規表示式裡括號的表示式為另外一組匹配規則

捕獲括號:被匹配的子字串可以在結果陣列的元素 [1]-[n] 中找到,或在被定義的 regexp 物件的屬性 $1-$9 中找到。

**舉例:

let reg = /\d+(\d+)/

reg.exec('123456abcd')

// ["123456abcd", "abcd", index: 0, input: "123456abcd", groups: undefined]

console.log(regexp.$1)

// "abcd"

複製**

在這個正規表示式裡我們括號期望的是一組非數字的匹配項,並且執行匹配後可在執行結果的[1]或者regexp.$1得到匹配值。

正規表示式括號的分組在實際開發中對於我們解決問題有非常大的用處,例如string.replace()這個方法

**舉例:

let str = '123abc'

let reg = /(\d+)(\d+)/

let newstr = str.replace(reg, '$2$1')

console.log(newstr) // abc123

str.replace(reg, function(word, $1, $2))

複製**

使用正規表示式應用於字串處理,在上面的例子裡我們很容易得就把數字和字母的匹配項互換位置。

在另外一種情況下如果不想要捕獲這個匹配項,但是又需要加括號匹配條件,我們可以使用非捕獲括號

非捕獲括號:匹配項不能夠從結果陣列的元素 [1]-[n] 或已被定義的 regexp 物件的屬性 $1-$9 再次訪問到。

**舉例:

let reg = /\d+(?:\d+)/

reg.exec('123456abcd')

// ["123456abcd", index: 0, input: "123456abcd", groups: undefined]

複製**

在例子裡執行匹配後括號裡的匹配項不會再出現結果裡。

反向引用:乙個反向引用(back reference),指向正規表示式中第 n 個括號(從左開始數)中匹配的子字串。

**舉例:

reg = /(\d+)\d+\1/

reg.exec('123abc123')

// ["123abc123", "123", index: 0, input: "123abc123", groups: undefined]

複製**

在正規表示式裡\1代表的是\d+,當我們在表示式裡有需要重複的時候可以用這種寫法。

零寬斷言:指乙個用來描述或者匹配一系列符合某個句法規則的字串的單個字串。

(?=pattern) 正向先行斷言:代表字串中的乙個位置,緊接該位置之後的字串行能夠匹配pattern。

(?!pattern) 負向先行斷言:代表字串中的乙個位置,緊接該位置之後的字串行不能匹配pattern。

(?<=pattern) 正向後行斷言:代表字串中的乙個位置,緊接該位置之前的字串行能夠匹配pattern。

(? 正規表示式的括號有時候用來表達斷言,具體的細節我們在下面問內容詳細說。

貪婪模式與非貪婪模式也是正則裡面比較常見的問題了,平時也會經常應用於開發中解決問題。理解貪婪模式和非貪婪模式對我們理解正則引擎執行匹配非常有幫助。

貪婪模式會匹配盡可能多的字元,貪婪模式用於匹配優先量詞修飾的子表示式,匹配優先量詞包括:「」、「」、「?」、「*」和「+」

**舉例:

let reg = /\d*/

reg.exec('1234567890')

["1234567890", index: 0, input: "1234567890", groups: undefined]

複製**

*號代表匹配任意次數,用大括號代表即,在貪婪模式下盡可能多的匹配,在例子中因為整個字串完全匹配,所以匹配值為 1234567890。

非貪婪模式會匹配盡可能少的字元,在匹配量詞後面加上問號就可觸發非貪婪模式:「?」、「?」、「??」、「*?」和「+?」

**舉例:

let reg = /\d*?/

reg.exec('1234567890')

// ["", index: 0, input: "1234567890", groups: undefined]

複製**

*號代表匹配任意次數,用大括號代表即,因為*號可代表匹配0次,在非貪婪模式下盡可能少的匹配,所以在這個例子裡匹配項為空,即不匹配任何字串。

正規表示式的斷言功能非常強大,學習正則的斷言應用,對於解決我們開發中的問題提供了新的思路。

在理解斷言的執行過程可能會稍微有點繞,但是作為乙個開發肯定要有一顆愛折騰的心,哈哈。

下面將只使用正向先行斷言來說明斷言的執行,其他的三個模式也是大同小異。

先看乙個簡單例子:

let reg = /abc(?=123)/

reg.exec('abc123')

// ["abc", index: 0, input: "abc123", groups: undefined]

let reg2 = /abc(?=1234)/

reg2.exec('abc123')

// null

let reg3 = /abc(?=12)/

reg3.exec('abc123')

// ["abc", index: 0, input: "abc123", groups: undefined]

複製**

先按照正則的字面意思理解,/abc(?=123)/期望的匹配為即匹配abc,且abc後面的字串能夠滿足括號的匹配規則,注意的是括號裡面可以為其他正規表示式,並不是說abc後面只能包含123,而是後面可以滿足括號的匹配則為斷言成功。

在reg2的匹配過程中,因為abc後面的字串不滿足括號的匹配規則,所以斷言失敗,執行匹配也失敗了。

在這幾個例子裡還沒有體現出我們概念裡說的意思,重溫一下正向先行斷言的概念

(?=pattern) 正向先行斷言:代表字串中的乙個位置,緊接該位置之後的字串行能夠匹配pattern

概念裡說的意思斷言是在字串中尋找符合斷言的乙個位置

舉例說明:

let reg = /(?=abc).*/

reg.exec('123abc123')

// ["abc123", index: 3, input: "123abc123", groups: undefined]

複製**

先分析正規表示式,在滿足abc匹配條件的位置後面匹配任意字元。在這個例子裡,存在abc滿足斷言的匹配規則,但是為什麼匹配到的是abc123?

在這裡就回到我們的標題,零寬斷言,零寬的意思就是執行斷言是不會消耗我們正規表示式在匹配過程中的字串,並且,斷言是在幫我們確定符合斷言匹配規則的位置。所以,(?=abc)會幫我們確定乙個斷言成功的位置,即3和a之間的位置,然後在這個斷言成功的位置開始執行匹配(.*)。

let reg = /(?=abc)\d+/

reg.exec('123abc123')

// null

複製**

在上面的例子中,雖然abc的斷言成功,但是斷言只是幫我們確定乙個位置,然後再執行\d+匹配規則,因為斷言是不會消耗字串,所以實際上以abc123去和\d+匹配,最後匹配結果為null。

基於此我們可以使用斷言幫我們從一開始檢索整個字串是否滿足某些規則,有助於提公升匹配效率。

如下例子,我們可以使用斷言從一開始判斷整個字串是否全部由數字組成,如果斷言失敗,則不執行匹配,這對於我們應用於表單校驗非常有助於提公升效率。

reg = /(?=^\d+$)\d+/

reg.exec('123456') // 123456

reg.exec('123456a') // null

複製**

另外沒有介紹到的三種模式也是大同小異,在這裡也就不重複贅述。但是兩種後行斷言可能會存在相容性問題,後行斷言應該是es2018新增的規範。

零寬斷言的重點是要理解「零寬」以及「位置」這兩個點。

最後總結一下:正規表示式是一門非常實用的工具語言,基本上只要學習了就能夠對於我們實際開發中產生幫助,平時某些開發工具中也可以使用正規表示式去檢索某些文件,對於提公升效率真的是幫助非常大。

正規表示式深入學習

find name txt 查詢.目錄下的任何txt檔案 為萬用字元 任意字元 任意個任意字元 可以是0個 至少是乙個任意字元 轉義字元 匹配 d 數字 d?0個或1個數字 d 1 n個數字 d3個數字 d3 5個數字 d 0 n個數字 b 單詞邊界 b 非單詞邊界 例如 bis b 表示句子中的t...

深入學習正規表示式的使用

目標 深入學習正規表示式的寫法。字元類 abc a b 或 c 簡單類 abc 任何字元,除了 a b 或 c 否定 a za z a 到 z 或 a 到 z,兩頭的字母包括在內 範圍 a d m p a 到 d 或 m 到 p a dm p 並集 a z def23 d e 或 f 交集 a z ...

正規表示式學習

概念 正規表示式,就是用某種模式去匹配一類字串的乙個公式。基礎 下表列出了所有的元字元和對它們的乙個簡短的描述。簡單例子 vi 命令作用 s g 把乙個或者多個空格替換為乙個空格 s 去掉行尾的所有空格 s 在每一行頭上加入乙個空格 s 0 9 0 9 去掉行首的所有數字字元 s b aeio g ...