Linux系統程式設計(17)——正規表示式進階

尹成發表於2014-07-26

 

C的變數和Shell指令碼變數的定義和使用方法很不相同,表達能力也不相同,C的變數有各種型別,而Shell指令碼變數都是字串。同樣道理,各種工具和程式語言所使用的正規表示式規範的語法並不相同,表達能力也各不相同,有的正規表示式規範引入很多擴充套件,能表達更復雜的模式,但各種正規表示式規範的基本概念都是相通的。

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

 

字元類:如上例的x和y,它們在模式中表示一個字元,但是取值範圍是一類字元中的任意一個。

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

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

 

規定一些特殊語法表示字元類、數量限定符和位置關係,然後用這些特殊語法和普通字元一起表示一個模式,這就是正規表示式。

 

字元類

字元

含義

舉例

.

匹配任意一個字元

abc.可以匹配abcd、abc9等

[]

匹配括號中的任意一個字元

[abc]d可以匹配ad、bd或cd

-

在[]括號內表示字元範圍

[0-9a-fA-F]可以匹配一位十六進位制數字

^

位於[]括號內的開頭,匹配除括號中的字元之外的任意一個字元

[^xy]匹配除xy之外的任一字元,因此[^xy]1可以匹配a1、b1但不匹配x1、y1

[[:xxx:]]

grep工具預定義的一些命名字元類

[[:alpha:]]匹配一個字母,[[:digit:]]匹配一個數字

 

數量限定符

字元

含義

舉例

?

緊跟在它前面的單元應匹配零次或一次

[0-9]?\.[0-9]匹配0.0、2.3、.5等,由於.在正規表示式中是一個特殊字元,所以需要用\轉義一下,取字面值

+

緊跟在它前面的單元應匹配一次或多次

[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+匹配email地址

*

緊跟在它前面的單元應匹配零次或多次

[0-9][0-9]*匹配至少一位數字,等價於[0-9]+,[a-zA-Z_]+[a-zA-Z_0-9]*匹配C語言的識別符號

{N}

緊跟在它前面的單元應精確匹配N次

[1-9][0-9]{2}匹配從100到999的整數

{N,}

緊跟在它前面的單元應匹配至少N次

[1-9][0-9]{2,}匹配三位以上(含三位)的整數

{,M}

緊跟在它前面的單元應匹配最多M次

[0-9]{,1}相當於[0-9]?

{N,M}

緊跟在它前面的單元應匹配至少N次,最多M次

[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}匹配IP地址

 

再次注意grep找的是包含某一模式的行,而不是完全匹配某一模式的行。再舉個例子,如果文字檔案的內容是

aaabc
aad
efg


查詢a*這個模式的結果是三行都被找出來了

$ egrep 'a*' testfile
aabc
aad
efg


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

 

 

常用的元字元

.        匹配除換行符以外的任意字元

\w    匹配字母或數字或下劃線或漢字

\s      匹配任意的空白符

\d     匹配數字

\b     匹配單詞的開始或結束

^       匹配字串的開始

$       匹配字串的結束

元字元^(和數字6在同一個鍵位上的符號)和$都匹配一個位置,這和\b有點類似。^匹配你要用來查詢的字串的開頭,$匹配結尾。這兩個程式碼在驗證輸入的內容時非常有用,比如一個網站如果要求你填寫的QQ號必須為5位到12位數字時,可以使用:^\d{5,12}$。

這裡的{5,12}和前面介紹過的{2}是類似的,只不過{2}匹配只能不多不少重複2次,{5,12}則是重複的次數不能少於5次,不能多於12次,否則都不匹配。

因為使用了^和$,所以輸入的整個字串都要用來和\d{5,12}來匹配,也就是說整個輸入必須是5到12個數字,因此如果輸入的QQ號能匹配這個正規表示式的話,那就符合要求了。

和忽略大小寫的選項類似,有些正規表示式處理工具還有一個處理多行的選項。如果選中了這個選項,^和$的意義就變成了匹配行的開始處和結束處。

 

位置限定符

字元

含義

舉例

^

匹配行首的位置

^Content匹配位於一行開頭的Content

$

匹配行末的位置

;$匹配位於一行結尾的;號,^$匹配空行

\<

匹配單詞開頭的位置

\<th匹配... this,但不匹配ethernet、tenth

\>

匹配單詞結尾的位置

p\>匹配leap ...,但不匹配parent、sleepy

\b

匹配單詞開頭或結尾的位置

\bat\b匹配... at ...,但不匹配cat、atexit、batch

\B

匹配非單詞開頭和結尾的位置

\Bat\B匹配battery,但不匹配... attend、hat ...

 

位置限定符可以幫助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這一行過濾掉了。

 

 

其它特殊字元

字元

含義

舉例

\

轉義字元,普通字元轉義為特殊字元,特殊字元轉義為普通字元

普通字元<寫成\<表示單詞開頭的位置,特殊字元.寫成\.以及\寫成\\就當作普通字元來匹配

()

將正規表示式的一部分括起來組成一個單元,可以對整個單元使用數量限定符

([0-9]{1,3}\.){3}[0-9]{1,3}匹配IP地址

|

連線兩個子表示式,表示或的關係

n(o|either)匹配no或neither

 

如果你想查詢元字元本身的話,比如你查詢.,或者*,就出現了問題:你沒辦法指定它們,因為它們會被解釋成別的意思。這時你就得使用\來取消這些字元的特殊意義。因此,你應該使用\.和\*。當然,要查詢\本身,你也得用\\。

相關文章