正則表達式(四)

以前我們用grep在一個文件中找出包含某些字符串的行,比如在頭文件中找出一個宏定義。其實grep還可以找出符合某個模式(Pattern)的一類字符串。例如找出所有符合[email protected]模式的字符串(也就是email地址),要求x字符可以是字母、數字、下劃線、小數點或減號,email地址的每一部分可以有一個或多個x字符,例如[email protected][email protected],當然符合這個模式的不全是合法的email地址,但至少可以做一次初步篩選,篩掉a.bc@d等肯定不是email地址的字符串。再比如,找出所有符合yyy.yyy.yyy.yyy模式的字符串(也就是IP地址),要求y0-9的數字,IP地址的每一部分可以有1-3y字符。

如果要用grep查找一個模式,如何表示這個模式,這一類字符串,而不是一個特定的字符串呢?從這兩個簡單的例子可以看出,要表示一個模式至少應該包含以下信息:

字符類(Character Class):如上例的xy,它們在模式中表示一個字符,但是取值範圍是一類字符中的任意一個。

數量限定符(Quantifier):郵件地址的每一部分可以有一個或多個x字符,IP地址的每一部分可以有1-3y字符。

各種字符類以及普通字符之間的位置關係:例如郵件地址分三部分,用普通字符@.隔開,IP地址分四部分,用.隔開,每一部分都可以用字符類和數量限定符描述。爲了表示位置關係,還有位置限定符(Anchor)的概念,將在下面介紹。

規定一些特殊語法表示字符類、數量限定符和位置關係,然後用這些特殊語法和普通字符一起表示一個模式,這就是正則表達式(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

$ 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的正則表達式有BasicExtended兩種規範,它們之間的區別下一節再解釋。另外還有fgrep命令,相當於grep -F,表示只搜索固定字符串而不搜索正則表達式模式,不會按正則表達式的語法解釋後面的參數。

注意正則表達式參數用單引號括起來了,因爲正則表達式中用到的很多特殊字符在Shell中也有特殊含義(例如),只有用單引號括起來才能保證這些字符原封不動地傳給grep命令,而不會被Shell解釋掉。

192.168.1.1符合上述模式,由三個.隔開的四段組成,每段都是13個數字,所以這一行被找出來了,可爲什麼1234.234.04.5678也被找出來了呢?因爲grep找的是包含某一模式的行,這一行包含一個符合模式的字符串234.234.04.567。相反,123.4234.045.678這一行不包含符合模式的字符串,所以不會被找出來。

grep是一種查找過濾工具,正則表達式在grep中用來查找符合模式的字符串。其實正則表達式還有一個重要的應用是驗證用戶輸入是否合法,例如用戶通過網頁表單提交自己的email地址,就需要用程序驗證一下是不是合法的email地址,這個工作可以在網頁的Javascript中做,也可以在網站後臺的程序中做,例如PHPPerlPythonRubyJavaC,所有這些語言都支持正則表達式,可以說,目前不支持正則表達式的編程語言實在很少見。除了編程語言之外,很多UNIX命令和工具也都支持正則表達式,例如grepvisedawkemacs等等。“正則表達式”就像“變量”一樣,它是一個廣泛的概念,而不是某一種工具或編程語言的特性。

基本語法

我們知道C的變量和Shell腳本變量的定義和使用方法很不相同,表達能力也不相同,C的變量有各種類型,而Shell腳本變量都是字符串。同樣道理,各種工具和編程語言所使用的正則表達式規範的語法並不相同,表達能力也各不相同,有的正則表達式規範引入很多擴展,能表達更復雜的模式,但各種正則表達式規範的基本概念都是相通的。本節介紹egrep(1)所使用的正則表達式,它大致上符合POSIX正則表達式規範,詳見regex(7)(看這個man page對你的英文絕對是很好的鍛鍊)。希望讀者仿照上一

字符類

數量限定符

再次注意grep找的是包含某一模式的行,而不是完全匹配某一模式的行。

例如有如下文本:

aaabc

aad

efg

查找a*這個模式的結果。會發現,三行都被找了出來。

$ egrep 'a*' testfile

aaabc

aad

efg

a匹配0個或多個a,而第三行包含0a,所以也包含了這一模式。單獨用a這樣的正則表達式做查找沒什麼意義,一般是把a*作爲正則表達式的一部分來用。

位置限定符

位置限定符可以幫助grep更準確地查找。

例如上一節我們用[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}查找IP地址,找到這兩行

192.168.1.1

1234.234.04.5678

如果用^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$查找,就可以把1234.234.04.5678這一行過濾掉了。

其它特殊字符

Basic正則和Extended正則區別

以上介紹的是grep正則表達式的Extended規範,Basic規範也有這些語法,只是字符?+{}|()應解釋爲普通字符,要表示上述特殊含義則需要加\轉義。如果用grep而不是egrep,並且不加-E參數,則應該遵照Basic規範來寫正則表達式。



發佈了19 篇原創文章 · 獲贊 2 · 訪問量 9882
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章