以前我們用grep
在一個檔案中找出包含某些字元串的行,比如在標頭檔中找出一個宏定義。其實grep
還可以找出符合某個模式(Pattern)的一類字元串。例如找出所有符合xxxxx@xxxx.xxx
模式的字元串(也就是email地址),要求x字元可以是字母、數字、下劃線、小數點或減號,email地址的每一部分可以有一個或多個x字元,例如abc.d@ef.com
、1_2@987-6.54
,當然符合這個模式的不全是合法的email地址,但至少可以做一次初步篩選,篩掉a.b
、c@d
等肯定不是email地址的字元串。再比如,找出所有符合yyy.yyy.yyy.yyy
模式的字元串(也就是IP地址),要求y是0-9的數字,IP地址的每一部分可以有1-3個y字元。
如果要用grep
查找一個模式,如何表示這個模式,這一類字元串,而不是一個特定的字元串呢?從這兩個簡單的例子可以看出,要表示一個模式至少應該包含以下信息:
規定一些特殊語法表示字元類、數量限定符和位置關係,然後用這些特殊語法和普通字元一起表示一個模式,這就是正則表達式(Regular Expression)。例如email地址的正則表達式可以寫成[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+
,IP地址的正則表達式可以寫成[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
。下一節介紹正則表達式的語法,我們先看看正則表達式在grep
中怎麼用。例如有這樣一個文本檔案testfile
:
192.168.1.1 1234.234.04.5678 123.4234.045.678 abcde
查找其中包含IP地址的行:
$ egrep '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' testfile 192.168.1.1 1234.234.04.5678
egrep
相當於grep -E
,表示採用Extended正則表達式語法。grep
的正則表達式有Basic和Extended兩種規範,它們之間的區別下一節再解釋。另外還有fgrep
命令,相當於grep -F
,表示只搜索固定字元串而不搜索正則表達式模式,不會按正則表達式的語法解釋後面的參數。
注意正則表達式參數用單引號括起來了,因為正則表達式中用到的很多特殊字元在Shell中也有特殊含義(例如\),只有用單引號括起來才能保證這些字元原封不動地傳給grep
命令,而不會被Shell解釋掉。
192.168.1.1
符合上述模式,由三個.
隔開的四段組成,每段都是1到3個數字,所以這一行被找出來了,可為什麼1234.234.04.5678
也被找出來了呢?因為grep
找的是包含某一模式的行,這一行包含一個符合模式的字元串234.234.04.567
。相反,123.4234.045.678
這一行不包含符合模式的字元串,所以不會被找出來。
grep
是一種查找過濾工具,正則表達式在grep
中用來查找符合模式的字元串。其實正則表達式還有一個重要的應用是驗證用戶輸入是否合法,例如用戶通過網頁表單提交自己的email地址,就需要用程序驗證一下是不是合法的email地址,這個工作可以在網頁的Javascript中做,也可以在網站後台的程序中做,例如PHP、Perl、Python、Ruby、Java或C,所有這些語言都支持正則表達式,可以說,目前不支持正則表達式的編程語言實在很少見。除了編程語言之外,很多UNIX命令和工具也都支持正則表達式,例如grep、vi、sed、awk、emacs等等。“正則表達式”就像“變數”一樣,它是一個廣泛的概念,而不是某一種工具或編程語言的特性。