刨根究底正則表達式(1):開篇

2021-02-18 刨根究底學編程



1、常規學習過程很痛苦

計算機領域中有一些非常基礎、重要以及應用廣泛,但卻又特別容易讓人困惑、非常難以理解的主題,這包括了字符編碼、字節序(即大小端表示)、浮點數實現、日期時間處理以及正則表達式等。

正則表達式目前市面上並不缺乏專業著作,比如那本被譽為正則表達式學習聖經的《精通正則表達式》就很值得一讀,另外該書的譯者餘晟先生所寫的《正則指引》也不錯。

如果僅用於入門,則《正則表達式必知必會》肯定不能錯過,還有網上流傳極廣的《正則表達式30分鐘入門教程》也是不錯的入門資料。

但是,結合我自身痛苦的正則表達式學習經歷和運用體會,僅有這些是遠遠不夠的。

記得被大家稱之為「輪子哥」的大神級程式設計師vczh在知乎上說過,當初被正則表達式虐得一氣之下,乾脆自己寫了一個正則引擎(源碼託管在Github上),才算真正徹底搞懂正則表達式(於是被戲稱為「一言不合」就造輪子)。

當然不是每個程式設計師都能像「輪子哥」這樣生猛,但即便都有這麼生猛,似乎也沒必要都像他一樣自己花費大量時間再造一個正則引擎的「輪子」。

那到底應該怎樣才能最高性價比(主要是最高時間-成本比)地掌握正則表達式這個神器呢?

2、一旦用過了再也回不去的「神器」

正則表達式是典型的那種你沒用過的話,不覺得對自己有什麼影響,可是一旦用過了,就再也回不去了的「神器」。


當然,我這裡所說的「用過」,不是指簡單地會用一些基本功能,而是指能夠熟練地運用正則表達式的基本功能和高級功能。只要你用得越熟練,你就會越驚嘆於其高效、強大與神奇。

看到這裡,我相信某些接觸過正則表達式、會使用一些基本功能的童鞋,心裡或許在犯嘀咕了:神器是神器,可這玩意兒看起來就像天書一樣,也太難學、太難懂了,要達到熟練運用的程度,談何容易!

短短的一個正則表達式,或許不到10個字符,其中的每個字符都認識,但它們連在一起,卻讓人越看越迷惑,越想越迷糊……

其實,這正是我學習正則表達式時的真實心情。

是的,正則表達式既然被捧上了神器級別的高度,自然是有著相當強大的功能,而強大的功能就意味著其有非常深厚的內涵,也就意味著有很多需要注意的細節。

3、關鍵在於掌握其獨特的「性格」和「脾氣」

注意,我這裡並沒有說正則表達式是由於複雜而難以理解,這是因為,深厚的內涵不等於複雜,細節很多不意味著難以理解。

看到這裡,或許有人有意見了,正則表達式還不算複雜?還不夠難理解?

其實,我真正想說的是,繁複或許是真的,雜亂倒未必。因此,簡單地說正則表達式複雜,似乎不夠準確而客觀。

正如跟一個牛叉而又性格獨特的人打交道,關鍵不在於糾結其性格的獨特、脾氣的古怪,而是重在充分了解並理解其獨特的性格、古怪的脾氣,然後在此基礎上與Ta進行良好的溝通,以便能好好發揮其牛叉之處。

學習並熟練掌握正則表達式的過程也是如此——關鍵在於先要摸透其「性格」到底獨特在哪裡,其「脾氣」又究竟古怪在何方。一旦摸清楚了其「性格」,其「脾氣」,學習起來就事半功倍了。


因此,我下面準備從我自己的角度,先嘗試著來分析一下正則表達式那獨特的「性格」與古怪的「脾氣」,看看究竟為什么正則表達式給那麼多人的感覺都是那麼難以「親近」。


1、高度簡潔、高度抽象是難學的關鍵

正則表達式有一個非常明顯的特點:高度簡潔、高度抽象。正則表達式中短短的幾個字符,或許就代表了一段複雜的處理邏輯和匹配算法。

我們知道,程序代碼是對現實事務處理邏輯的抽象,而正則表達式則是對複雜的字符匹配程序代碼的進一步抽象;也就是說,高度簡潔的正則表達式,其背後所對應的是字符匹配程序代碼,而字符匹配程序代碼,背後對應的是字符匹配處理邏輯。

因此可以這麼認為,字符匹配處理邏輯,抽象為字符匹配程序代碼;字符匹配程序代碼,再進一步抽象為高度簡潔的正則表達式。

所以說,高度簡潔的正則表達式也是高度抽象的。

2、其他難學的原因

當然,正則表達式之所以難學、難理解,除了由於正則表達式具有高度簡潔、高度抽象的特點之外,大致上應該還有以下幾個原因:

1)學習者不求甚解,不了解正則引擎內部的基本原理

作為正則表達式的使用者,不需要深入了解正則引擎內部原理的技術實現細節,那是正則引擎開發者更應該了解的;但若完全不了解其基本工作原理和運行機制,也是不足取的。

2)有多個多義元字符,特別容易使人混淆、迷亂

比如-、+、?、^,尤其是元字符?,既可以作為量詞表示其所限定的子表達式為可選(即匹配0次或1次),也可以置於量詞之後表示懶惰匹配,而且還有很多特殊分組結構中用到它。

比如(?<name>sub-regex)、(?:sub-regex)、(?>sub-regex)、(?=sub-regex)、(?!sub-regex)、(?<=sub-regex)、(?<!sub-regex)、(?|sub-regex)、(?modifier-modifier)、(?(condition)|)、(?R)、(?num)、(?#comment)等。

還記得我自己當初剛開始學習的時候,一看到正則表達式中的問號?,就有一種獨自在風中凌亂的感覺。

3)轉義也是難點

什麼情況下需要轉義,什麼情況下不需要轉義,貌似複雜得令人抓狂。

當然,其實是有一定的規律的,掌握了這些規律,再遇到轉義問題,就不至於心潮澎湃了。

4)學習期望與學習方法不對

不應該期望一次性記住、學會並熟練運用,正確的學習姿勢應該是先簡單入門,對一些基本的規則與元字符大致了解一遍,有個印象就好,在需要時再回過頭來看,不用刻意去強行記憶。

然後接下來就是在工作中多實踐、多運用,邊學、邊深入、邊熟練。

5)有用於入門的好教程、備忘單,也有用於深入的大部頭專著,但卻缺乏好的速查手冊

由於需要邊學、邊深入、邊熟練,因此,平時手頭邊更需要的不是簡單的入門教程、備忘單(Cheat Sheet),也不僅僅是知識點分散於各處的大部頭專著(知識點分散導致查找起來不方便,用於深入學習原理是不錯,但不夠實用),而是一本速查手冊。

速查手冊按語法元素將知識點綜合在一起進行編排的、在需要回過頭來看時能夠隨時快速翻查。

這樣,在實踐運用中遇到問題就可方便隨時快速翻查,而這一點恰恰對於正則表達式這種不可能短期內快速掌握並熟練運用的專業工具的學習與使用非常重要。

6)沒有使用好的學習工具

你知道regex101.com、RegexBuddy、regexper.com等正則表達式的專業網站和專業工具嗎?

這些堪稱學習正則表達式的神器,可令學習事半功倍,但很多人不知道,或知道但很少使用。


1、從兩個不同的角度和維度來看

對於正則表達式的分析和解讀,目前大多數文章和書籍多集中在正則表達式自身,比如對正則表達式的各個元字符、元轉義序列以及匹配原理的分析和解讀上。

當然,這些自然也是很有必要的,而且是學習的主要內容,是理解正則表達式所必需的。然而,很多人在看了大量這類文章和書籍之後,仍然覺得正則表達式很難看懂,不好理解。

難道就沒有更好的學習姿勢了嗎?

其實,理解一個事物,往往可以有不同的角度和維度。多個角度和多個維度相結合,對於事物的理解可以更為深入,而且經常還會有「原來如此」這樣豁然開朗的暢快感。

下面是我理解一個事物通常所用到的兩個不同的角度和維度:

一是,深入事物本身去理解它內在的原理和機制等底層邏輯;

二是,跳出事物本身,站在一個更高的維度和層面,橫向地與其他同類事物進行比較,縱向地去分析它的發展與演變。

正如蘇軾那首著名的哲理詩《題西林壁》所說的,「不識廬山真面目,只緣身在此山中」。很多時候往往就是這樣,當你只從該事物本身來看的話,就如在雲裡霧裡,是遠遠不夠的。

而一旦跳出到該事物之外,站在更高的一個維度來看,則又正如王安石的《登飛來峰》中所說:「不畏浮雲遮望眼,只緣身在最高層」,登高望遠,則一覽無餘了。

2、刨根究底正則表達式的根源和本質

對正則表達式而言,前者正是目前大多數文章和書籍在做的;而後者,卻很少有文章和書籍能夠跳出正則表達式,站在更高的維度或層面來分析和解讀正則表達式。這裡就包括了《精通正則表達式》和《正則指引》兩書。

這裡需要特別強調一下的是,我絕沒有貶低上述這兩本專著及其作者和/或譯者之意,而且恰恰相反,這兩本專著正是本系列文章的重要參考書。尤其無論是作為《精通正則表達式》的譯者,還是作為《正則指引》的著者,餘晟先生都得上是專業而又嚴謹的。

即便是對於前者而言,目前大多數文章和書籍也多半是一上來就正則表達式本身來說正則表達式,而往往沒有去深挖正則表達式背後的根源和本質。

從根源上來講,正則表達式是為了解決一個基本問題——文本的查找匹配問題;從本質上來講,正則表達式也是一門程式語言,並且具有典型的編程範式。

當然,正則表達式的功能除了查找匹配文本之外,還包括提取、驗證、替換、切分文本等,但這些功能都是在查找匹配文本功能基礎上衍生出來的。

然而文本查找匹配問題的解決方案有其歷史演變的過程,只有理解了該過程,以及將正則表達式放在該歷史過程的背景上,才能更好、更徹底地理解正則表達式。

而站在正則表達式也是一門程式語言的角度,如果能夠從縱向程式語言發展史和橫向編程範式的角度來看正則表達式,則會有高屋建瓴、綱舉目張之感。

後面的文章,我會先從文本查找匹配功能的歷史演變過程講起,隨後再從程式語言發展史角度來看看正則表達式到底是一門怎樣的語言,以及具有什麼典型的編程範式。

然後,在此基礎上,再來深入學習正則表達式,我相信,你一定會有跟以往完全不一樣的感覺和理解。

長按掃碼 關注本公號

我們一起持續進步

微信號:paogenjiudi

好文章正如好產品一樣,是不斷迭代、持續完善出來的。

可是,公眾號中的文章一旦發布出來後,就不允許再作任何修改了。

因此,如果你期待看到本公眾號中系列文章後續的持續改進版本,以及希望能夠一起學習交流技術,歡迎掃碼加入我的「刨根究底學編程」知識星球,我在那裡等待和大家一起共同持續進步。

越早加入越划算哦,因為自本周起每隔一段時間(暫定為約1~2周)將上調10元年費,視加入人數情況再決定最高封頂年費。

另外,本訂閱號文章也會在服務號「笨笨阿林」中轉載,雖然服務號一周只能更新一次,不如訂閱號及時,但更不容易錯過,歡迎一併掃碼關注,這樣還可以同時閱讀我的其他非技術類文章:

相關焦點

  • 正則表達式
    在我看來,正則表達式的主要用途有兩種:①查找特定的信息②查找並編輯特定的信息,也就是我們經常用的替換。。比如我們要在Word,記事本等裡面使用快捷鍵Ctrl+F,進行查找一個特定的字符,或者替換一個字符,這就使用了正則表達式。         正則表達式的功能非常強大,尤其是在文本數據進行處理中顯得更加突出。
  • 正則表達式在VBA中間是如何應用?正則表達式的實現方式?
    Hi,大家好,本章節開始將會從零開始和大家用圖文的方式,讓你從零基礎學會正則表達式!有興趣的小夥伴可以持續關注我,或者在專欄中進行查看自我學習,願與君攜手前行!在上一個章節說到正則表達式的入門級知識點,本節將會與大家分享一下正則表達式的是具體實現方式是怎麼樣的?
  • python正則表達式
    微信公眾號:學點啥玩點啥小白友好型python正則表達式 1#第7章 模式匹配與正則表達式
  • Python中的正則表達式
    正則表達式基本語法下面我們通過下表來學習一下正則表達式中的元字符和含義:*注意事項:(1)數量詞的貪婪模式與非貪婪模式正則表達式通常用於在文本中查找匹配的字符串。Python裡數量詞默認是貪婪的(在少數語言裡也可能是默認非貪婪),總是嘗試匹配儘可能多的字符;非貪婪的則相反,總是嘗試匹配儘可能少的字符。
  • Matlab 正則表達式
    正則表達式是一個非常重要的編程概念,主流的程式語言都對正則表達式進行了很好的支持,Matlab也不例外。本期推文就讓我們來總結一下Matlab提供的正則表達式吧!1 引言正則表達式(Regular Expression),又稱規則表達式,本質上是一串字符,它定義了某種字符串模式,通常被用來檢索、替換那些符合某個模式(規則)的文本。
  • Python 正則表達式
    最簡單的正則表達式就是普通字符串,可以匹配其自身。比如,正則表達式 『hello』 可以匹配字符串 『hello』。要注意的是,正則表達式並不是一個程序,而是用於處理字符串的一種模式,如果你想用它來處理字符串,就必須使用支持正則表達式的工具,比如 Linux 中的 awk, sed, grep,或者程式語言 Perl, Python, Java 等等。
  • VBS正則表達式
    下面的 Visual Basic scripting Edition 正則表達式可以匹配 'aac'、'abc'、'acc'、'adc'如此等等,同樣也可以匹配 'a1c'、'a2c'、a-c'以及 a#c':/a.c/等價的 VBscript. 正則表達式為:"a.c"如果試圖匹配一個包含文件名的字符串,其中句點 (.)
  • 實戰JS正則表達式
    [新建正則表達式]:var  regexp = /aabb/g; //g可省 var  regexp = new Regexp("xyz","g"); //第二個參數可省區別在於:1.採用字面量的寫法新建的正則表達式對象在代碼編譯時就會生成,是平常開發中常用的方式;2.採用構造函數生成的正則對象要在代碼運行時生成。
  • Python正則表達式總結
    大多數程式語言的正則表達式設計都師從Perl,所以語法基本相似,不同的是每種語言都有自己的函數去支持正則,今天我們就來學習 Python中關於 正則表達式的函數。re模塊主要定義了9個常量、12個函數、1個異常,每個常量和函數豬哥都會通過實際代碼案例講解,讓大家能更直觀的了解其作用!註:為避免出現代碼格式錯亂,豬哥儘量使用代碼截圖演示哦。
  • 正則表達式替換函數
    導讀在上篇推文《正則表達式匹配和提取函數》中簡單介紹了正則表達式的匹配和提取函數,並用一些簡單的例子向大家說明如何利用正則表達式匹配和提取文本。
  • PHP正則表達式的快速學習方法
    1、入門簡介簡單的說,正則表達式是一種可以用於模式匹配和替換的強有力的工具。我們可以在幾乎所有的基於UNIX系統的工具中找到正則表達式的身影,例如,vi編輯器,Perl或PHP腳本語言,以及awk或sed shell程序等。
  • 正則表達式基礎筆記
    正則表達式定義正則表達式聲明1.普通方式
  • JavaScript高級什麼是正則以及正則表達式的簡單運用
    在實際開發中 ,經常會用到一些表單的驗證 ,提交表單的時候一般都會預校驗 ,比如手機號填寫是否合格 ,用戶暱稱填寫是否規範等 ,這些就要用到正則表達式什麼是正則表達式?用於匹配規律規則的表達式,正則表達式最初是科學家對人類神經系統的工作原理的早期研究,現在在程式語言中有廣泛的應用。正則表通常被用來檢索、替換那些符合某個模式(規則)的文本。
  • Perl教程 - 正則表達式
    ,它與Tcl等語言中的正則表達式有一定的相似之處,因此如果學習過相關正則表達式的話這個不會很難。Perl的正則表達式中如果出現(),則發生匹配或替換後()內的模式被Perl解釋器自動依次賦給系統$1,$2.
  • 看完你就會正則表達式了
    以下是正文(為了適應難度,做了稍許調整)1.什麼是正則表達式正則表達式,又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。
  • 正則表達式語法
    原子是正則表達式中最基本的組成單位,每個正則表達式中至少包含一個原子。
  • Oracle 正則表達式(一)
    Oracle的正則表達式(regular expression)簡單介紹目前,正則表達式已經在很多軟體中得到廣泛的應用
  • Java 正則表達式教程及示例
    本教程旨在幫助你駕馭Java正則表達式,同時也幫助我複習正則表達式。什麼是正則表達式?正則表達式定義了字符串的模式。正則表達式可以用來搜索、編輯或處理文本。正則表達式並不僅限於某一種語言,但是在每種語言中有細微的差別。Java正則表達式和Perl的是最為相似的。
  • Python正則表達式急速入門
    正則表達式在程序開發中會經常用到,比如數據(格式)驗證、替換字符內容以及提取字符串內容等等情況都會用到,但是目前許多開發人員對於正則表達式只是處於了解或者是基本會用的階段。一旦遇到大批量使用正則表達式的情況(例如網絡爬蟲)可以說基本上就抓瞎了。這篇文章我將帶領大家利用 Python 來學習一下正則表達式。
  • 乾貨:java正則表達式匯總
    Email 正則表達式模式  ^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.IP位址正則表達式模式  ^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.  ([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?