深入淺出之正規表示式

2021-06-07 17:51:30 字數 4097 閱讀 8829

1.      什麼是正規表示式

基本說來,正規表示式是一種用來描述一定數量文字的模式。regex代表regular express。本文將用<>來表示一段具體的正規表示式。

一段文字就是最基本的模式,簡單的匹配相同的文字。

2.      不同的正規表示式引擎

正規表示式引擎是一種可以處理正規表示式的軟體。通常,引擎是更大的應用程式的一部分。在軟體世界,不同的正規表示式並不互相相容。本教程會集中討論perl 5 型別的引擎,因為這種引擎是應用最廣泛的引擎。同時我們也會提到一些和其他引擎的區別。許多近代的引擎都很類似,但不完全一樣。例如.net正則庫,jdk正則包。

3.      文字元號

最基本的正規表示式由單個文字元號組成。如<>,它將匹配字串中第一次出現的字元「a」。如對字串「jack is a boy」。「j」後的「a」將被匹配。而第二個「a」將不會被匹配。

類似的,<>會匹配「about cats and dogs」中的「cat」。這等於是告訴正規表示式引擎,找到乙個<>,緊跟乙個<>,再跟乙個<>。

要注意,正規表示式引擎預設是大小寫敏感的。除非你告訴引擎忽略大小寫,否則<>不會匹配「cat」。

·        特殊字元

對於文字字元,有11個字元被保留作特殊用途。他們是:

[ ] \ ^ $ . | ? * + ( )

這些特殊字元也被稱作元字元。

如果你想在正規表示式中將這些字元用作文字字元,你需要用反斜槓「\」對其進行換碼 (escape)。例如你想匹配「1+1=2」,正確的表示式為<<1\+1=2>>.

需要注意的是,<<1+1=2>>也是有效的正規表示式。但它不會匹配「1+1=2」,而會匹配「123+111=234」中的「111=2」。因為「+」在這裡表示特殊含義(重複1次到多次)。

在程式語言中,要注意,一些特殊的字元會先被編譯器處理,然後再傳遞給正則引擎。因此正規表示式<<1\+2=2>>在c++中要寫成「1\\+1=2」。為了匹配「c:\temp」,你要用正規表示式<>。而在c++中,正規表示式則變成了「c:\\\\temp」。

·        不可顯示字元

可以使用特殊字串行來代表某些不可顯示字元:

<<\t>>代表tab(0x09)

<<\r>>代表回車符(0x0d)

<<\n>>代表換行符(0x0a)

要注意的是windows中文字檔案使用「\r\n」來結束一行而unix使用「\n」。

4.      正規表示式引擎的內部工作機制

知道正規表示式引擎是如何工作的有助於你很快理解為何某個正規表示式不像你期望的那樣工作。

有兩種型別的引擎:文字導向(text-directed)的引擎和正則導向(regex-directed)的引擎。jeffrey friedl把他們稱作dfa和nfa引擎。本文談到的是正則導向的引擎。這是因為一些非常有用的特性,如「惰性」量詞(lazy quantifiers)和反向引用(backreferences),只能在正則導向的引擎中實現。所以毫不意外這種引擎是目前最流行的引擎。

你可以輕易分辨出所使用的引擎是文字導向還是正則導向。如果反向引用或「惰性」量詞被實現,則可以肯定你使用的引擎是正則導向的。你可以作如下測試:將正規表示式<>應用到字串「regex not」。如果匹配的結果是regex,則引擎是正則導向的。如果結果是regex not,則是文字導向的。因為正則導向的引擎是「猴急」的,它會很急切的進行表功,報告它找到的第乙個匹配 。

·        正則導向的引擎總是返回最左邊的匹配

這是需要你理解的很重要的一點:即使以後有可能發現乙個「更好」的匹配,正則導向的引擎也總是返回最左邊的匹配。

當把<>應用到「he captured a catfish for his cat」,引擎先比較<>和「h」,結果失敗了。於是引擎再比較<>和「e」,也失敗了。直到第四個字元,<>匹配了「c」。<>匹配了第五個字元。到第六個字元<>沒能匹配「p」,也失敗了。引擎再繼續從第五個字元重新檢查匹配性。直到第十五個字元開始,<>匹配上了「catfish」中的「cat」,正規表示式引擎急切的返回第乙個匹配的結果,而不會再繼續查詢是否有其他更好的匹配。

5.      字符集

字符集是由一對方括號「」括起來的字元集合。使用字符集,你可以告訴正規表示式引擎僅僅匹配多個字元中的乙個。如果你想匹配乙個「a」或乙個「e」,使用<<[ae]>>。你可以使用<>匹配gray或grey。這在你不確定你要搜尋的字元是採用美國英語還是英國英語時特別有用。相反,<>將不會匹配graay或graey。字符集中的字元順序並沒有什麼關係,結果都是相同的。

你可以使用連字元「-」定義乙個字元範圍作為字符集。<<[0-9]>>匹配0到9之間的單個數字。你可以使用不止乙個範圍。<<[0-9a-fa-f] >>匹配單個的十六進製制數字,並且大小寫不敏感。你也可以結合範圍定義與單個字元定義。<<[0-9a-fxa-fx]>>匹配乙個十六進製制數字或字母x。再次強調一下,字元和範圍定義的先後順序對結果沒有影響。

·        字符集的一些應用

查詢乙個可能有拼寫錯誤的單詞,比如<> 或 <>。

查詢程式語言的識別符號,<>。(*表示重複0或多次)

查詢c風格的十六進製制數<<0[xx][a-fa-f0-9]+>>。(+表示重複一次或多次)

·        取反字符集

在左方括號「[」後面緊跟乙個尖括號「^」,將會對字符集取反。結果是字符集將匹配任何不在方括號中的字元。不像「.」,取反字符集是可以匹配回車換行符的。

需要記住的很重要的一點是,取反字符集必須要匹配乙個字元。<>並不意味著:匹配乙個q,後面沒有u跟著。它意味著:匹配乙個q,後面跟著乙個不是u的字元。所以它不會匹配「iraq」中的q,而會匹配「iraq is a country」中的q和乙個空格符。事實上,空格符是匹配中的一部分,因為它是乙個「不是u的字元」。

如果你只想匹配乙個q,條件是q後面有乙個不是u的字元,我們可以用後面將講到的向前檢視來解決。

·        字符集中的元字元

需要注意的是,在字符集中只有4個 字元具有特殊含義。它們是:「] \ ^ -」。「]」代表字符集定義的結束;「\」代表轉義;「^」代表取反;「-」代表範圍定義。其他常見的元字元在字符集定義內部都是正常字元,不需要轉義。例如,要搜尋星號*或加號+,你可以用<<[+*]>>。當然,如果你對那些通常的元字元進行轉義,你的正規表示式一樣會工作得很好,但是這會降低可讀性。

在字符集定義中為了將反斜槓「\」作為乙個文字字元而非特殊含義的字元,你需要用另乙個反斜槓對它進行轉義。<<[\\x]>>將會匹配乙個反斜槓和乙個x。「]^-」都可以用反斜槓進行轉義,或者將他們放在乙個不可能使用到他們特殊含義的位置。我們推薦後者,因為這樣可以增加可讀性。比如對於字元「^」,將它放在除了左括號「[」後面的位置,使用的都是文字字元含義而非取反含義。如<<[x^]>>會匹配乙個x或^。<>會匹配乙個「]」或「x」。<<[-x]>>或<<[x-]>>都會匹配乙個「-」或「x」。

·        字符集的簡寫

因為一些字符集非常常用,所以有一些簡寫方式。

<<\d>>代表<<[0-9]>>;

<<\w>>代表單詞字元。這個是隨正規表示式實現的不同而有些差異。絕大多數的正規表示式實現的單詞字符集都包含了<>。

<<\s>>代表「白字元」。這個也是和不同的實現有關的。在絕大多數的實現中,都包含了空格符和tab符,以及回車換行符<<\r\n>>。

字符集的縮寫形式可以用在方括號之內或之外。<<\s\d>>匹配乙個白字元後面緊跟乙個數字。<<[\s\d]>>匹配單個白字元或數字。<<[\da-fa-f]>>將匹配乙個十六進製制數字。

取反字符集的簡寫

<<[\s]>> = <<[^\s]>>

<<[\w]>> = <<[^\w]>>

<<[\d]>> = <<[^\d]>>

·        字符集的重複

如果你用「?*+」操作符來重複乙個字符集,你將會重複整個字符集。而不僅是它匹配的那個字元。正規表示式<<[0-9]+>>會匹配837以及222。

如果你僅僅想重複被匹配的那個字元,可以用向後引用達到目的。我們以後將講到向後引用

正規表示式30分鐘入門教程

記於2010.8.2黯風夜隱

深入淺出正規表示式

正規表示式其實還是蠻簡單的,因為它沒有很強的邏輯在裡頭,我們只需要按照它的規則從頭開始依次去讀就好了 話雖這麼說,我相信很多人一開始接觸正則,當看到那一連串 亂七八糟 的字元時,都會一臉懵逼,這是啥玩意?然後就自然而然的認為這東西很複雜,接著打心底就牴觸使用正則,然後開始在網上搜看是否有現成的表示式...

深入淺出之正規表示式 2

5.字符集字符集是由一對方括號 括起來的字元集合。使用字符集,你可以告訴正規表示式引擎僅僅匹配多個字元中的乙個。如果你想匹配乙個 a 或乙個 e 使用 ae 你可以使用 匹配gray或grey。這在你不確定你要搜尋的字元是採用美國英語還是英國英語時特別有用。相反,將不會匹配graay或graey。字...

正規表示式深入淺出 深入淺出資料分析

618買的 深入淺出資料分析 前段時間終於看完了,發現閒魚上的市場還不錯,就擺在上面 了,在被賣出之前,我寫了一篇總結,沒想到的是,文章儲存失誤了,現在書已經賣出去了,想重寫只能靠回憶了。深入淺出資料分析 這本書給我最深的感受是excel上 資料分析 和 規劃求解 兩個選項的使用,在這本書之前我知道...