我們知道C的變數和Shell腳本變數的定義和使用方法很不相同,表達能力也不相同,C的變數有各種類型,而Shell腳本變數都是字元串。同樣道理,各種工具和編程語言所使用的正則表達式規範的語法並不相同,表達能力也各不相同,有的正則表達式規範引入很多擴展,能表達更複雜的模式,但各種正則表達式規範的基本概念都是相通的。本節介紹egrep(1)
所使用的正則表達式,它大致上符合POSIX正則表達式規範,詳見regex(7)
(看這個man page對你的英文絶對是很好的鍛鍊)。希望讀者仿照上一節的例子,一邊學習語法,一邊用egrep
命令做實驗。
表 32.1. 字元類
字元 | 含義 | 舉例 |
---|---|---|
. | 匹配任意一個字元 | abc. 可以匹配abcd 、abc9 等 |
[] | 匹配括號中的任意一個字元 | [abc]d 可以匹配ad 、bd 或cd |
- | 在[] 括號內表示字元範圍 | [0-9a-fA-F] 可以匹配一位十六進制數字 |
^ | 位於[] 括號內的開頭,匹配除括號中的字元之外的任意一個字元 | [^xy] 匹配除xy 之外的任一字元,因此[^xy]1 可以匹配a1 、b1 但不匹配x1 、y1 |
[[:xxx:]] | grep 工具預定義的一些命名字元類 | [[:alpha:]] 匹配一個字母,[[:digit:]] 匹配一個數字 |
表 32.2. 數量限定符
字元 | 含義 | 舉例 |
---|---|---|
? | 緊跟在它前面的單元應匹配零次或一次 | [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*
作為正則表達式的一部分來用。
表 32.3. 位置限定符
字元 | 含義 | 舉例 |
---|---|---|
^ | 匹配行首的位置 | ^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
這一行過濾掉了。
表 32.4. 其它特殊字元
字元 | 含義 | 舉例 |
---|---|---|
\ | 轉義字元,普通字元轉義為特殊字元,特殊字元轉義為普通字元 | 普通字元< 寫成\< 表示單詞開頭的位置,特殊字元. 寫成\. 以及\ 寫成\\ 就當作普通字元來匹配 |
() | 將正則表達式的一部分括起來組成一個單元,可以對整個單元使用數量限定符 | ([0-9]{1,3}\.){3}[0-9]{1,3} 匹配IP地址 |
| | 連接兩個子表達式,表示或的關係 | n(o|either) 匹配no 或neither |
以上介紹的是grep
正則表達式的Extended規範,Basic規範也有這些語法,只是字元?+{}|()
應解釋為普通字元,要表示上述特殊含義則需要加\
轉義。如果用grep
而不是egrep
,並且不加-E
參數,則應該遵照Basic規範來寫正則表達式。