首頁 > web前端 > js教程 > 主體

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

青灯夜游
發布: 2022-03-09 20:13:59
轉載
2042 人瀏覽過

正規表示式是對字串操作的一種邏輯公式,是在處理文字資料時的重要而複雜的技術。那怎麼快速掌握正規表示式?以下本篇文章推薦一種學習方法:透過 AST。希望對大家有幫助!

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

字串的處理基本上都會用正規表示式,用它來做字串的匹配、提取、替換等很方便。

但是正規表示式的學習還是有些難度的,例如貪婪匹配、非貪婪匹配、捕獲子組、非捕獲子組等概念,不止初學者難理解,有很多工作幾年的人都不理解。

那正規表示式怎麼學比較好?怎麼快速掌握正規表示式呢?

推薦一個我覺得很不錯的學習正規的方式:透過 AST 來學習

正規表示式的符合原理是把模式字串 parse 成 AST,然後經過這個 AST 去匹配目標字串。

模式字串中的各種資訊在 parse 之後都會保存在 AST 裡面。 AST 是 abstract syntax tree,抽象語法樹的意思,顧名思義,是按照語法結構組織的一棵樹,那麼從 AST 的結構上自然可以輕易的知道正則表達式支持的語法。

怎麼看正規表示式的 AST 呢?

可以透過astexplorer.net 這個網站來視覺化的檢視:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

切換parse 的語言為RegExp,就可以做正規表達式的AST 的可視化。

就像前面所說,AST 是按照文法來組織的一棵樹,那麼從它的結構上自然能容易地理清各種文法。

那麼我們就從AST 的角度來學習下各種文法吧:

/abc/

先從簡單的開始,/abc/ 這樣一個正規可以匹配'abc' 的字串,它的AST 是這樣的:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

3 個Char,值分別是a、b、c,類型是simple。那之後的匹配就是遍歷 AST,分別配對這三個字元了。

我們用 exec 的 api 測試了下:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

第 0 個元素是符合的字串,index 是匹配字串的開始下標。 input 是輸入的字串。

再來試下特殊的字元:

/\d\d\d/

/\d\d\d/ 是符合三個數字的意思,\ d 是正規支援的有特殊意義的元字元(meta char)。

透過AST 我們也可以看出來,它們雖然也是Char,但類型確是meta:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#可以透過\d 的元字元來匹配任意數字:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

哪些是meta char 哪些是simple char,透過AST 來看一目了然。

/[abc]/

正規支援透過 [] 的方式來指定一組字符,也就是說匹配其中任何一種字符都行。

透過 AST 我們也可以看出來,它被包裹了一層 CharacterClass,就是字元類別的意思,也就是匹配它所包含的任意一種字元都行。

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

測試下也確實是如此:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#/a{1,3}/

#正規表示式支援指定某個字元重複多少次,以{from,to} 的形式,

例如/b{1,3}/ 表示字元b 重複1 到3 次,/[abc] {1,3}/ 表示這個a/b/c 字元類別重複1 到3 次。

透過AST 可以看出來,這種語法叫做Repetition(重複):

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#他有個quantifier 的屬性表示量詞,這裡的型別是range ,從1 到3。

正規也支持一些量詞的簡寫,例如 表示 1 到無數次、* 表示 0 到無數次、? 表示 0 或 1 次。

分別是不同類型的量詞:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

有同學可能會問,這裡的 greedy 屬性是啥意思呢?

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

greedy 是貪婪的意思,這個屬性就表示這個 Repetition 是貪婪匹配還是非貪婪匹配。

如果在量詞後面加個?,你會發現greedy 變成false 了,也就是切換到了非貪婪匹配:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

那貪婪和非貪婪是指啥呢?

我們看個例子就知道了。

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

預設 Repetition 的匹配是貪婪的,只要滿足條件就一直匹配下去,所以這裡 acbac 都能匹配到。

量詞後加個? 就切換到了非貪婪,就只會匹配第一個了:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

這就是貪婪匹配和非貪婪匹配,透過AST 我們能夠清楚的知道貪婪和非貪婪是針對重複語法來說的,預設是貪婪匹配,在量詞後面加個? 就可以切換到非貪婪。

(aaa)bbb(ccc)

正規表示式支援透過()把符合到的一部分字串放到子群組裡回傳。

透過 AST 看一下:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

對應的 AST 就叫做 Group。

而且你會發現它有個 capturing 的屬性,預設是 true:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

這就是啥意思呢?

這就是子組捕獲的語法。

如果不想捕獲子組,可以這樣寫 (?:aaa)

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#看,capturing 變成 false 了。

那捕獲和非捕獲有什麼區別呢?

我們試試看:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

哦,原來 Group 的 capturing 屬性代表的是是否提取的意思啊。

我們透過AST 可以看出來,捕獲是針對子組來說的,預設是捕獲,也就是提取子組的內容,可以透過?: 切換到非捕獲,就不會提取子組的內容了。

我們對用AST 來了解正規語法已經輕車熟路了,那來看點難的:

/bbb(?=ccc)/

正規表達式支援透過(?=xxx) 的語法來表示先行斷言,用來判斷某個字串是否前面是某個字串。

透過AST 可以看到這個語法叫做Assertion,且型別為lookahead,也就是往前看,只符合前面的意思:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

##這是啥意思呢?為啥要這麼寫?和 /bbb(ccc)/ 還有 /bbb(?:ccc)/有啥差別呢?

我們試試看:

1怎麼快速掌握正規表示式?透過 AST 來學正規語法!

從結果可以看出來:

/bbb(ccc)/ 配對了ccc 的子群組並且提取出來了這個子組,因為預設子組是捕獲的。

/bbb(?:ccc)/ 匹配了 ccc 的子組但沒有提取出來,因為我們透過 ?: 設定了子組不捕獲。

/bbb(?=ccc)/ 匹配了 ccc 的子組也沒有提取出子組,說明也是非捕獲的。它和 ?: 的差別是 ccc 沒有出現在配對結果裡。

這就是先行斷言(lookahead assertion)的性質:

先行斷言代表某段字串前面是某段字串,對應的子組是非捕獲的,而且斷言的字串不會出現在匹配結果中。

如果後面不是跟著那段字串就不符合:

怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#/bbb(?!ccc)/

#把?= 改成?! 之後意思就變了,透過AST 看一下:

2怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#雖然還是先行斷言lookahead assertion,但是多了個negative 為true 的屬性。

這個意思很明顯,本來是前面是某段字串,否定之後就是前面不是某段字串。

那符合結果剛好就反過來了:

2怎麼快速掌握正規表示式?透過 AST 來學正規語法!

現在前面不是某段字串的話才匹配了,這就是否定先行斷言。

/(?

有先行斷言自然也有後行斷言,也就是後面是某段字串才符合。

2怎麼快速掌握正規表示式?透過 AST 來學正規語法!

同理,也可以否定:

2怎麼快速掌握正規表示式?透過 AST 來學正規語法!

#(?

2怎麼快速掌握正規表示式?透過 AST 來學正規語法!

(?

2怎麼快速掌握正規表示式?透過 AST 來學正規語法!

先行斷言、後行斷言就是最難理解的正規表示式語法了,透過AST 來學習是不是就容易理解多了~

總結

正規表示式是處理字串的很方便的工具,但它的學習還是有些難度的,像貪婪匹配、非貪婪匹配、捕獲子組、非捕獲子組、先行斷言、後行斷言等語法很多人都搞不清楚。

我推薦透過 AST 來學習正規則,AST 是按照語法結構來組織的一顆物件樹,各種語法透過 AST 節點的名字和屬性可以輕易的理清楚。

例如我們透過AST 理清楚了:

重複語法(Repetition)就是字元量詞的形式,預設是貪婪匹配(greedy 為true),代表一直匹配到不匹配為止,量詞後加個? 就切換成了非貪婪匹配,匹配到一個字符就停止。

子組語法(Group)是用來提取某段字串的,預設是捕獲(capturing 為true),代表需要提取,可以透過(?:xxx)切換到非捕獲,只匹配不提取。

斷言語法(Assertion)代表前面或後面有某段字串,分為先行斷言(lookahead assertion)和後行斷言(lookbehind assertion),語法分別是(?= xxx)和(?

是各種文件對語法理解的深還是編譯器對語法理解的深?

那還用問,一定是編譯器呀!

那麼透過它按照語法 parse 出來的語法樹來學習語法自然比文件更好。

正規表示式是這樣,其他的語法的學習也是這樣,能用 AST 學會的語法,就不需要看文件。

更多node相關知識,請造訪:nodejs 教學

以上是怎麼快速掌握正規表示式?透過 AST 來學正規語法!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:juejin.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!