【转】刨根究底正则表达式(1):开篇
奇葩的正則表達式
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、regexper.com、RegexBuddy等正則表達式的專業網站和專業工具嗎?
這些堪稱學習正則表達式的神器,可令學習事半功倍,但很多人不知道,或知道但很少使用。
什么才是更好的學習姿勢
1、從兩個不同的角度和維度來看
對于正則表達式的分析和解讀,目前大多數文章和書籍多集中在正則表達式自身,比如對正則表達式的各個元字符、元轉義序列以及匹配原理的分析和解讀上。
當然,這些自然也是很有必要的,而且是學習的主要內容,是理解正則表達式所必需的。然而,很多人在看了大量這類文章和書籍之后,仍然覺得正則表達式很難看懂,不好理解。
難道就沒有更好的學習姿勢了嗎?
其實,理解一個事物,往往可以有不同的角度和維度。多個角度和多個維度相結合,對于事物的理解可以更為深入,而且經常還會有“原來如此”這樣豁然開朗的暢快感。
下面是我理解一個事物通常所用到的兩個不同的角度和維度:
一是,深入事物本身去理解它內在的原理和機制等底層邏輯; 二是,跳出事物本身,站在一個更高的維度和層面,橫向地與其他同類事物進行比較,縱向地去分析它的發展與演變。
正如蘇軾那首著名的哲理詩《題西林壁》所說的,“不識廬山真面目,只緣身在此山中”。很多時候往往就是這樣,當你只從該事物本身來看的話,就如在云里霧里,是遠遠不夠的。
而一旦跳出到該事物之外,站在更高的一個維度來看,則又正如王安石的《登飛來峰》中所說:“不畏浮云遮望眼,只緣身在最高層”,登高望遠,則一覽無余了。
2、刨根究底正則表達式的根源和本質
對正則表達式而言,前者正是目前大多數文章和書籍在做的;而后者,卻很少有文章和書籍能夠跳出正則表達式,站在更高的維度或層面來分析和解讀正則表達式。這里就包括了《精通正則表達式》和《正則指引》兩書。
這里需要特別強調一下的是,我絕沒有貶低上述這兩本專著及其作者和/或譯者之意,而且恰恰相反,這兩本專著正是本系列文章的重要參考書。尤其無論是作為《精通正則表達式》的譯者,還是作為《正則指引》的著者,余晟先生都得上是專業而又嚴謹的。
即便是對于前者而言,目前大多數文章和書籍也多半是一上來就正則表達式本身來說正則表達式,而往往沒有去深挖正則表達式背后的根源和本質。
從根源上來講,正則表達式是為了解決一個基本問題——文本的查找問題(也稱為匹配問題);從本質上來講,正則表達式也是一門編程語言,并且具有典型的編程范式。
當然,正則表達式的功能除了查找文本之外,還包括提取、驗證、替換、切分文本等,但這些功能都是在查找文本功能基礎上衍生出來的。
然而文本查找問題的解決方案有其歷史演變的過程,只有理解了該過程,以及將正則表達式放在該歷史過程的背景上,才能更好、更徹底地理解正則表達式。
而站在正則表達式也是一門編程語言的角度,如果能夠從縱向編程語言發展史和橫向編程范式的角度來看正則表達式,則會有高屋建瓴、綱舉目張之感。
后面的文章,我會先從文本查找功能的歷史演變過程講起,隨后再從編程語言發展史角度來看看正則表達式到底是一門怎樣的語言,以及具有什么典型的編程范式。
然后,在此基礎上,再來深入學習正則表達式,我相信,你一定會有跟以往完全不一樣的感覺和理解。
總結
以上是生活随笔為你收集整理的【转】刨根究底正则表达式(1):开篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】wpf从我炫系列1----布局控件
- 下一篇: 省点花锦鲤卡怎么用?锦鲤卡和骑士卡有什么