輕鬆理解正則表達式

本文是幫助剛接觸正則表達式或用過還沒有弄懂的童鞋理解正則表達式,主要描述了正則表達式是個什麼東東,而不是討論用法和工作原理。不過也歡迎高手批評指正,以更好的幫助新手。

無論是Java、Shell、Python、Perl都用正則表達式,說明它肯定是個好東西,那它到底是一個什麼樣東東呢?

正則表達式曾是我學Shell時最頭大的一個問題,當時總以爲他是條命令啥的,顯然他不是,也顯然是個表達式,那什麼叫表達式呢,這個概念先不管,應該都聽說過算術表達式吧,那算術表達式是啥呢,怎麼描述呢,在數學課程中是這樣描述的:由數字和運算符號組成的式子,可以簡單清晰地記錄或描述計算過程和內容【本句摘自百度百科】,我們只看前半句,說明是個式子,式子都知道吧,簡單的說是一句話,有特定含義的一句話,當然編程語言中的算術表達式還是個式子,正則表達式也是個式子。

現在知道它也是一種表達式了,那他是幹嘛用的呢?算術表達式是用於描述計算過程和內容的,正則表達式是描述了一批而不是一個字符串,爲什麼要描述一批字符串呢,比如你要顯示當成目錄下所有的以.c爲後輟的文件,怎麼辦呢,都知道linux下顯示文件是用ls命令,如果linux懂人的自然語言,那那樣就可以這樣:

$ ls 所有以.c爲後輟的文件

可惜它不懂,所以會報錯,你可能認爲他不懂中文,你也可以用英文試試。

那我們怎麼把這個的意思傳達給它呢,肯定是要商定一個共同語言,正則表達式就是人與程序的一種共同語言,含通配符的表達式也是一種,不過通配符簡單點,所以我們先用通配符試試:

elwin@Ubuntu64:~/work$ ls
1.c  1.java  2.c  2.java  3.c  file1.txt
elwin@Ubuntu64:~/work$ ls *.c
1.c  2.c  3.c
其中星號“*”表示任意字符串,於是用這個簡單的*.c就是描述了所用以.c結尾的字符串,這是一批字符串,而不是一個,如果另一個字符串屬於這一批字符串,就可以說該字符串與該表達式匹配成功,於是上例中所以匹配成功的都顯示出來了。(說明一點,上述的通配符表達式不是被ls擴展,而是被shell擴展的,文章最後的附錄有個腳本驗證,有興趣可以試試,但不知道這點並不會阻礙你對本文的理解)

雖然那不是正則表達式,但思想是一樣的,本質是表達式中的某些的字符有特殊含義,當然這個特殊含義是相對就言的,例如上面的星號“*”對你而言就是星號,但對Shell而言,星號代表任意字符串,而在正則表達式中又不同,因爲正則表達式與通配符就語法和符號代表的特殊含義是不同的,正規表達式的表達能力要強大得多,你可以認爲正則表達式是通配符升級版,其實正則表達式是一種計算機的一個重要理論,它被應用於編譯器的詞法分析,跟有窮自動機有重要的聯繫,關於歷史,先不討論了。與上面的等價的用正則表達式是這樣的:

.*\.c
暫時看不懂沒關係,下面慢慢解釋,我們先用sed試一下吧:
elwin@Ubuntu64:~/work$ ls |sed -n '/.*\.c$/p'
1.c
2.c
3.c
用斜槓裏面包括的(不含斜槓)就是一個正則表達式,(這條組合命令你不知道沒關係,你只需要知道他的作用是:顯示當前目錄下,文件名符合該正則表達式的所有文件)。下面解釋一下這個正則表達式,其中的點“.”代表任意字符,星號“*”表示將前面的那個字符重複n次(包括0次),這兩個的意思就是將任意字符重複篇,如果正則表達式就這兩個,後面不寫了,那就表示世上所有字符串,我們再試一下吧:
elwin@Ubuntu64:~/work$ ls |sed -n '/.*/p'    
1.c
1.java
2.c
2.java
3.c
file1.txt

看吧,所有文件都列出來了,說明都匹配成功了。現在我們繼續分析剛剛的表達式,星號後面的反斜槓表示轉義,即把接下來的那個字符(這裏是點號)當作普通字符,沒有特珠含義,如果不在前面加上反斜槓就代表任何字符了,接下來的“c”在正則表達式裏屬於普通字符串,再接下來的美元符“$”表示換行符,於是整個表達式的意思就是:任意長度的字符串,連上“.c”,再接一個換行符,如果不接這個換行符,那“1.cc”也會被匹配,如:

elwin@Ubuntu64:~/work$ touch 1.cc
elwin@Ubuntu64:~/work$ ls |sed -n '/.*\.c/p'
1.c
1.cc
2.c
3.c

你可能有個疑問,哪到到底算特珠符號,哪些算普通符號呢,這當然有個規定了,這此特殊符號都有各自的含義,這種文章網上很多,大家可以搜索,也可以看man手冊(man grep就可以),也可以參考此文,本文主要目是幫助初學者理解正則表達式,而不是討論詳細用法。

還有一點需要說明,Shell、Java、Perl都有正規表達式,不過他們之間只有細微的區別,很多都是通用,其中以Perl中的正則表達式最強大,原因是Perl解釋器強大。


附錄

1.驗證shell會擴展星號的腳本,將以下內容保存到test.sh:

#!/bin/sh
echo "$*"
這裏的“$*”代表所以輸入參數。加上執行權限運行./test.sh *.c,結果如下:
elwin@Ubuntu64:~/work$ ls 
1.c  1.cc  1.java  2.c  2.java  3.c  file1.txt  test.sh
elwin@Ubuntu64:~/work$ ./test.sh *.c
1.c 2.c 3.c


說明:本文章純屬個人觀點,不保證絕對正確,歡迎大家批評和指正,同時我自己也會對本文不斷的更新和完善。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章