成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

能用 AST 搞明白的正則語法,就不需要看文檔

開發 前端
模式串中的各種信息在 parse 之后都會保存在 AST 里面。AST 是 abstract syntax tree,抽象語法樹的意思,顧名思義,是按照語法結構組織的一棵樹,那么從 AST 的結構上自然可以輕易的知道正則表達式支持的語法。

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

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

那正則表達式怎么學比較好?怎么快速掌握正則表達式呢?

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

正則表達式的匹配原理是把模式串 parse 成 AST,然后通過這個 AST 去匹配目標字符串。

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

怎么查看正則表達式的 AST 呢?

可以通過 astexplorer.net 這個網站來可視化的查看:

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

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

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

/abc/

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

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

我們用 exec 的 api 測試了下:

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

再來試下特殊的字符:

/\d\d\d/

/\d\d\d/ 是匹配三個數字的意思,\d 是正則支持的有特殊含義的元字符(meta char)。

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

可以通過 \d 的元字符來匹配任意數字:

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

/[abc]/

正則支持通過 [] 的方式來指定一組字符,也就是說匹配其中任意一種字符都行。

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

測試下也確實是這樣:

/a{1,3}/

正則表達式支持指定某個字符重復多少次,用 {from,to} 的形式,比如 /b{1,3}/ 表示字符 b 重復 1 到 3 次,/[abc]{1,3}/ 表示這個 a/b/c 這個字符類重復 1 到 3 次。

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

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

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

分別是不同類型的量詞:

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

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

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

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

我們看個例子就知道了。

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

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

這就是貪婪匹配和非貪婪匹配,通過 AST 我們能夠清楚的知道貪婪和非貪婪是針對重復語法來說的,默認是貪婪匹配,在量詞后加個 ? 就可以切換到非貪婪。

(aaa)bbb(ccc)

正則表達式支持通過()把匹配到的一部分字符串放到子組里返回。

通過 AST 看一下:

對應的 AST 就叫做 Group。

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

這是啥意思呢?

這就是子組捕獲的語法。

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

看,capturing 變為 false 了。

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

我們試一下:

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

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

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

/bbb(?=ccc)/

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

通過 AST 可以看到這種語法叫做 Assertion,并且類型為 lookahead,也就是往前看,只匹配前面的意思:

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

我們試一下:

從結果可以看出來:

/bbb(ccc)/ 匹配了 ccc 的子組并且提取出來了這個子組,因為默認子組是捕獲的。

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

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

這就是先行斷言(lookahead assertion)的性質:先行斷言代表某段字符串前面是某段字符串,對應的子組是非捕獲的,而且斷言的字符串不會出現在匹配結果中。

如果后面不是跟著那段字符串就不匹配:

/bbb(?!ccc)/

把 ?= 改成 ?! 之后意思就變了,通過 AST 看一下:

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

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

那匹配結果正好就反過來了:

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

/(?<=aaa)bbb/

有先行斷言自然也有后行斷言,也就是后面是某段字符串才匹配。

同理,也可以否定:

(?<=aaa)對應的 AST 很容易想到,就是 lookbehind assertion:

(?<!aaa)對應的 AST 就是加個 negative 屬性:

先行斷言、后行斷言就是最難理解的正則表達式語法了,通過 AST 來學習是不是就容易理解多了

總結

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

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

比如我們通過 AST 理清楚了:

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

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

斷言語法(Assertion)代表前面或后面有某段字符串,分為先行斷言(lookahead assertion)和后行斷言(lookbehind assertion),語法分別是(?=xxx)和 (?<=xxx),可以通過把 = 換成 ! 來表示否定(negative 為 true),意思正好反過來。

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

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

那么通過它按照語法 parse 出來的語法樹來學習語法自然比文檔更好。

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

責任編輯:武曉燕 來源: 神光的編程秘籍
相關推薦

2013-07-18 09:21:32

代碼文檔

2017-08-08 14:33:36

無服務計算服務器

2018-05-07 14:11:15

RootAndroidXposed

2020-02-29 15:58:37

iPhoneiOS安卓

2017-03-13 13:54:40

戴爾

2024-02-22 09:00:00

LogitMat數據集算法

2010-11-23 10:55:47

跳槽

2018-01-29 13:18:42

前端JavaScript

2012-08-23 09:50:07

測試測試人員軟件測試

2015-09-30 09:57:53

天分熱情工程師

2009-11-23 12:45:22

2016-10-26 13:35:43

云自動資源負載

2016-10-26 20:21:34

自動縮放可擴展性

2015-08-20 10:56:19

算法界面開發

2013-12-02 09:43:29

字符串編程

2022-09-14 15:10:40

前端架構

2022-02-15 07:26:34

web前端算法題

2014-01-17 13:09:48

Linux碎片整理

2021-12-12 22:20:47

Docker開發容器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本一区二区视频 | 欧美综合一区二区 | a级大片免费观看 | 日韩中文字幕 | 懂色中文一区二区三区在线视频 | 超碰综合 | 亚洲精品乱码久久久久久黑人 | 日韩中文字幕一区二区 | 在线一级片 | 男人天堂999| 免费在线看a | 国产欧美精品在线观看 | 欧美色欧美亚洲另类七区 | 久艹网站 | 欧美男人天堂 | 亚洲成av片人久久久 | 欧美一区二区免费 | 懂色av一区二区三区在线播放 | 一级黄色大片 | 欧美成人免费在线 | 操操日 | 日韩av成人 | 久草成人| 亚洲精品永久免费 | 中文字幕在线欧美 | www.4虎影院| 国产乱码精品一品二品 | 国产免费一区二区 | 久久久久久亚洲国产精品 | 一级国产精品一级国产精品片 | 国产一区二区自拍 | 欧美一区二区在线播放 | 久久免费国产 | 免费麻豆视频 | 日韩欧美在线视频 | 中文字字幕在线中文乱码范文 | 久草热视频| 精品久久久久久亚洲精品 | 欧美三级网站 | 欧美日韩精品在线免费观看 | 午夜影晥 |