咱們在使用正則表達式的時候,看到一坨繁瑣的式子常常頭大,若是轉換成圖形描述或許更加清晰點。本文介紹一個叫作 REGEXPER 的網站,REGEXPER 網站提供了一種工具,能夠把你的正則表達式轉換爲 鐵路圖(Railroad Diagram),經過鐵路圖,或許能讓咱們更清晰的理解咱們所編寫的正則表達式。git
看上面這張圖,這就是一張鐵路圖。這種圖能夠提供一種更直觀的方式讓咱們在面對正則裏面各類複雜的嵌套循環、可選的元素時化繁爲簡。這種圖最簡單的見解就是沿着線條從左日後看。若是你碰到一個分支branch, 這裏表示有多種選擇,你能夠任選一條路徑之一往下看(有的路徑還會在某一時刻再折回前面來,好比循環的時候)。爲了能完整的匹配整個圖中的表達式,你必須完整的從左到右依次走完整幅圖直到末尾。正則表達式
好比上面這幅圖,他的正則表達式是 Lions(?: and|,) tigers,? and bears\. Oh my!
。這個表達式將匹配 "Lions and tigers and bears. Oh my!" 或者 「Lions, tigers, and bears. Oh my!」, 即要麼使用 and
而不使用牛津逗號,要麼使用牛津逗號而不使用 and
。這幅圖首先描述了你必須先有一個 "Lions" 字符串,這個是必不可少的;接下來你能夠在 " and" 和 "," 之間進行選擇一個。無論你剛剛作的什麼選擇,接下來必須有一個 " tigers" 跟着。而這個 "tigers" 後面能夠有一個逗號也能夠在路徑上繞過這個逗號,所以後面這個逗號是可選的。在最後,必須跟着一個固定的字符串 " and bears. Oh my!"。express
下面咱們介紹鐵路圖中的一些元素的含義。工具
這種圖中最容易理解的部分就是那些基本的沒有選擇路徑之類的字符或文本串、轉義字符、任意字符了。網站
字面量是匹配一個精確的文本字符串。他們展現在一個 淺藍色
的塊裏面,內容會用 引號
包裹起來(讓你更容易看清任何前導或尾隨的空格)。
例如 /a/
或 /\d+你好/
中的你好
, 這種正則中的直接字面量,在 REGEXPER 網站中會用 淺藍色塊
包裹起來表示。ui
轉義序列,在圖上會用一個 綠色
的框來包裹,幷包含一個對要匹配的字符的描述。其中一些轉義字符他會給你轉成 16進製表示法
,甚至加上特殊的英文名稱以讓你看的更加清楚。spa
除了正常的轉義,下面幾種也跟轉義使用的色塊類型同樣:3d
這種跟上面的轉義序列同樣,都是用 綠色
塊包裹。只是通常會直接把你的進制直接顯示出來(不會加上英文名稱)。code
因爲元字符,其實就像 正則表達式中的轉義字符
,他在正常字符串中沒有具體轉義含義,但在正則表達式當中,卻能夠表達某些字符。所以他也算做前文 轉義序列
的一種。故用 綠色塊
包裹起來。而且 REGEXPER網站
會給該元字符加上英文名稱的說明,如 \d
會寫做 digit數字
.regexp
可見, 正常字符轉義
、 字符的進製表示
、正則中的元字符表示法
,他們因爲都是一種 字符
的表達形式,所以在 REEXPER 網站中都是用綠色塊來包裹表示。
正則圖例: /./
即 任意字符就是正則表達式中的點號。
正則中用 .
號來表示任意字符,而 .
在 REGEXPER 網站中會用黑色塊包裹,且顯示爲 Any Character
。他匹配任意的字符。
^
和 $
這倆字符表明行首行尾,比較特殊,也會用 黑色塊
包裹。
圖例: [#a-z\n][^$0-9\b]
字符集是指的多個字符的集合,字符集合會匹配或不匹配一堆的字符。字符集合在圖中表現爲 包裹着 literal字面量字符 和 轉義字符的塊
。在塊的頂部會用label標籤寫明 「包含」 仍是 "不包含"。
正則中通常是指的 [a-z]
或 [^a-z]
這種寫法。好比 [a-z] 它表達了從小寫a到小寫z這26個字母的集合。在 REGEXPER 網站中,字符集會用一個灰色塊把多個 淺藍色塊
和綠色塊
包裹起來。寓意: 多個單字符記號的集合。
在灰色塊的頂部,會有個英文提示,告訴你這個灰色塊是 "One Of" 仍是 "None of"。像 [a-z] 這種是OneOf
,則表示集合中包含 a 到 z;而像 1 則是NoneOf
,即表示集合中不包含a到z。
圖例: (example\s)(?=content)
子表達式由表達式周圍的虛線輪廓來表示。子捕獲組會用他的組序號做爲label標記在框的頂部。零寬斷言
和負向零寬斷言
這種捕獲組也都是這樣標記(譯者注: 由於 ?: ?= ?<=
這些都要在捕獲組中來使用,因此也會有個虛線框出現)。
圖例: one\s|two\W|three\t|four\n
交替是提供了一種選擇,他在圖中用多條路徑來表達正則表達式中的多種選擇。
量詞表達了一個表達式是應該重複仍是可選的。他們看起來有點像交替,經過圖的分支路徑、以及可能會轉回來的路徑來表達你的選擇方式。
這裏有一個約定:除非路徑上明確用箭頭指示了,不然你首選的路徑應該是先繼續直行,而不是繞行。
圖例: (?:greedy)*
和 (?:non-greedy)*?
這個 零或多
量詞指的是重複任意次數的 greedy 這個模式, 因爲默認沒箭頭的狀況下走直行,所以左圖咱們能夠看到:先優先執行的話會致使 greedy 循環屢次,所以咱們執行這個正則表達式的時候,會盡量多的匹配n次 greedy 字符串。
你們注意圖的右邊這個 non-greedy quantifier
哈。咱們看到他圖上給上半部分的這條路徑提早畫了一個 箭頭,而下半部分這條路徑箭頭沒有了(被堵死了)。這至關於讓你優先走上面的路徑,而下面原本是循環屢次
的路沒法走通,故意味着匹配結果是 重複non-greedy零次
。 咱們看正則表達式自己 (non-greedy)*?
,他實際上是在 (non-greedy)*
的基礎上,增長了一個所謂的 懶惰模式
,即告訴前面這個 *
採用懶惰模式儘量的少重複。
所以,假如這個正則用來匹配 "non-greedynon-greedynon-greedy",那麼他返回結果是空字符串。
圖例: (?:greedy)+
和 (?:greedy)+?
必選量詞是說必須匹配一個或多個。注意:它不像上面 0個或多個
似的在圖上容許直接跳過。 所以咱們從圖上看,能往右走的就只剩下中間一條路了。下面這條路其實你看它不是從左邊起點畫起出發的,而是從右邊往回走的一條路,但因爲沒有了箭頭,因此你也不能往回走了。
所以最終結果是,右邊這幅圖只能匹配 non-greedy
一次。其實從正則表達式自己來看,就是對 +
這個量詞采用懶惰模式進行匹配。
圖例: (?:greedy)?
和 (?:non-greedy)??
可選是指的匹配這個模式最多一次。能夠注意到他沒有能夠回到自身的路徑。
圖例: (?:greedy){5,10}
和 (?:non-greedy){5,10}?
區間是指的要把模式重複必定的數量的次數。這兩個例子都提供了一個 (5, 10) 次的區間,圖中的times label標籤寫明瞭這個分支要循環的次數(如圖中的4-9次)。這個圖中的次數值會比正則表達式中寫的次數少一次,這是由於這個模式至少在循環以前在路徑中會匹配一次。 因此對於本例,這個模式會在正常路徑中先匹配一次,而後進入循環匹配 4-9 次,總共是 5-10 次。
你們看右圖,實際上是 {5, 10}
的懶惰模式。他儘量的匹配少的次數,因此圖中就沒有畫箭頭,意在告訴你標籤中寫了4-9次,你儘量少的轉回來,只要知足要求(好比轉4次)就繼續日後走吧。
文章同步發表於個人博客: https://blog.cuiyongjian.com/...