計算機領域中有一些非常基礎、重要以及應用廣泛,但卻又特別容易讓人困惑、非常難以理解的主題,這包括了字符編碼、字節序(即大小端表示)、浮點數實現、日期時間處理以及正則表達式等。
正則表達式目前市面上並不缺乏專業著作,比如那本被譽為正則表達式學習聖經的《精通正則表達式》就很值得一讀,另外該書的譯者餘晟先生所寫的《正則指引》也不錯。
如果僅用於入門,則《正則表達式必知必會》肯定不能錯過,還有網上流傳極廣的《正則表達式30分鐘入門教程》也是不錯的入門資料。
但是,結合我自身痛苦的正則表達式學習經歷和運用體會,僅有這些是遠遠不夠的。
記得被大家稱之為「輪子哥」的大神級程式設計師vczh在知乎上說過,當初被正則表達式虐得一氣之下,乾脆自己寫了一個正則引擎(源碼託管在Github上),才算真正徹底搞懂正則表達式(於是被戲稱為「一言不合」就造輪子)。
當然不是每個程式設計師都能像「輪子哥」這樣生猛,但即便都有這麼生猛,似乎也沒必要都像他一樣自己花費大量時間再造一個正則引擎的「輪子」。
那到底應該怎樣才能最高性價比(主要是最高時間-成本比)地掌握正則表達式這個神器呢?
2、一旦用過了再也回不去的「神器」正則表達式是典型的那種你沒用過的話,不覺得對自己有什麼影響,可是一旦用過了,就再也回不去了的「神器」。
當然,我這裡所說的「用過」,不是指簡單地會用一些基本功能,而是指能夠熟練地運用正則表達式的基本功能和高級功能。只要你用得越熟練,你就會越驚嘆於其高效、強大與神奇。
看到這裡,我相信某些接觸過正則表達式、會使用一些基本功能的童鞋,心裡或許在犯嘀咕了:神器是神器,可這玩意兒看起來就像天書一樣,也太難學、太難懂了,要達到熟練運用的程度,談何容易!
短短的一個正則表達式,或許不到10個字符,其中的每個字符都認識,但它們連在一起,卻讓人越看越迷惑,越想越迷糊……
其實,這正是我學習正則表達式時的真實心情。
是的,正則表達式既然被捧上了神器級別的高度,自然是有著相當強大的功能,而強大的功能就意味著其有非常深厚的內涵,也就意味著有很多需要注意的細節。
3、關鍵在於掌握其獨特的「性格」和「脾氣」注意,我這裡並沒有說正則表達式是由於複雜而難以理解,這是因為,深厚的內涵不等於複雜,細節很多不意味著難以理解。
看到這裡,或許有人有意見了,正則表達式還不算複雜?還不夠難理解?
其實,我真正想說的是,繁複或許是真的,雜亂倒未必。因此,簡單地說正則表達式複雜,似乎不夠準確而客觀。
正如跟一個牛叉而又性格獨特的人打交道,關鍵不在於糾結其性格的獨特、脾氣的古怪,而是重在充分了解並理解其獨特的性格、古怪的脾氣,然後在此基礎上與Ta進行良好的溝通,以便能好好發揮其牛叉之處。
學習並熟練掌握正則表達式的過程也是如此——關鍵在於先要摸透其「性格」到底獨特在哪裡,其「脾氣」又究竟古怪在何方。一旦摸清楚了其「性格」,其「脾氣」,學習起來就事半功倍了。
因此,我下面準備從我自己的角度,先嘗試著來分析一下正則表達式那獨特的「性格」與古怪的「脾氣」,看看究竟為什么正則表達式給那麼多人的感覺都是那麼難以「親近」。
正則表達式有一個非常明顯的特點:高度簡潔、高度抽象。正則表達式中短短的幾個字符,或許就代表了一段複雜的處理邏輯和匹配算法。
我們知道,程序代碼是對現實事務處理邏輯的抽象,而正則表達式則是對複雜的字符匹配程序代碼的進一步抽象;也就是說,高度簡潔的正則表達式,其背後所對應的是字符匹配程序代碼,而字符匹配程序代碼,背後對應的是字符匹配處理邏輯。
因此可以這麼認為,字符匹配處理邏輯,抽象為字符匹配程序代碼;字符匹配程序代碼,再進一步抽象為高度簡潔的正則表達式。
所以說,高度簡潔的正則表達式也是高度抽象的。
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等正則表達式的專業網站和專業工具嗎?
這些堪稱學習正則表達式的神器,可令學習事半功倍,但很多人不知道,或知道但很少使用。
對於正則表達式的分析和解讀,目前大多數文章和書籍多集中在正則表達式自身,比如對正則表達式的各個元字符、元轉義序列以及匹配原理的分析和解讀上。
當然,這些自然也是很有必要的,而且是學習的主要內容,是理解正則表達式所必需的。然而,很多人在看了大量這類文章和書籍之後,仍然覺得正則表達式很難看懂,不好理解。
難道就沒有更好的學習姿勢了嗎?
其實,理解一個事物,往往可以有不同的角度和維度。多個角度和多個維度相結合,對於事物的理解可以更為深入,而且經常還會有「原來如此」這樣豁然開朗的暢快感。
下面是我理解一個事物通常所用到的兩個不同的角度和維度:
一是,深入事物本身去理解它內在的原理和機制等底層邏輯;
二是,跳出事物本身,站在一個更高的維度和層面,橫向地與其他同類事物進行比較,縱向地去分析它的發展與演變。
正如蘇軾那首著名的哲理詩《題西林壁》所說的,「不識廬山真面目,只緣身在此山中」。很多時候往往就是這樣,當你只從該事物本身來看的話,就如在雲裡霧裡,是遠遠不夠的。
而一旦跳出到該事物之外,站在更高的一個維度來看,則又正如王安石的《登飛來峰》中所說:「不畏浮雲遮望眼,只緣身在最高層」,登高望遠,則一覽無餘了。
2、刨根究底正則表達式的根源和本質對正則表達式而言,前者正是目前大多數文章和書籍在做的;而後者,卻很少有文章和書籍能夠跳出正則表達式,站在更高的維度或層面來分析和解讀正則表達式。這裡就包括了《精通正則表達式》和《正則指引》兩書。
這裡需要特別強調一下的是,我絕沒有貶低上述這兩本專著及其作者和/或譯者之意,而且恰恰相反,這兩本專著正是本系列文章的重要參考書。尤其無論是作為《精通正則表達式》的譯者,還是作為《正則指引》的著者,餘晟先生都得上是專業而又嚴謹的。
即便是對於前者而言,目前大多數文章和書籍也多半是一上來就正則表達式本身來說正則表達式,而往往沒有去深挖正則表達式背後的根源和本質。
從根源上來講,正則表達式是為了解決一個基本問題——文本的查找匹配問題;從本質上來講,正則表達式也是一門程式語言,並且具有典型的編程範式。
當然,正則表達式的功能除了查找匹配文本之外,還包括提取、驗證、替換、切分文本等,但這些功能都是在查找匹配文本功能基礎上衍生出來的。
然而文本查找匹配問題的解決方案有其歷史演變的過程,只有理解了該過程,以及將正則表達式放在該歷史過程的背景上,才能更好、更徹底地理解正則表達式。
而站在正則表達式也是一門程式語言的角度,如果能夠從縱向程式語言發展史和橫向編程範式的角度來看正則表達式,則會有高屋建瓴、綱舉目張之感。
後面的文章,我會先從文本查找匹配功能的歷史演變過程講起,隨後再從程式語言發展史角度來看看正則表達式到底是一門怎樣的語言,以及具有什麼典型的編程範式。
然後,在此基礎上,再來深入學習正則表達式,我相信,你一定會有跟以往完全不一樣的感覺和理解。
長按掃碼 關注本公號
我們一起持續進步
微信號:paogenjiudi
好文章正如好產品一樣,是不斷迭代、持續完善出來的。
可是,公眾號中的文章一旦發布出來後,就不允許再作任何修改了。
因此,如果你期待看到本公眾號中系列文章後續的持續改進版本,以及希望能夠一起學習交流技術,歡迎掃碼加入我的「刨根究底學編程」知識星球,我在那裡等待和大家一起共同持續進步。
越早加入越划算哦,因為自本周起每隔一段時間(暫定為約1~2周)將上調10元年費,視加入人數情況再決定最高封頂年費。
另外,本訂閱號文章也會在服務號「笨笨阿林」中轉載,雖然服務號一周只能更新一次,不如訂閱號及時,但更不容易錯過,歡迎一併掃碼關注,這樣還可以同時閱讀我的其他非技術類文章: