Linux系統程式設計(17)——正規表示式進階
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 |
如果你想查詢元字元本身的話,比如你查詢.,或者*,就出現了問題:你沒辦法指定它們,因為它們會被解釋成別的意思。這時你就得使用\來取消這些字元的特殊意義。因此,你應該使用\.和\*。當然,要查詢\本身,你也得用\\。
相關文章
- Linux系統程式設計(16)——正規表示式入門Linux程式設計
- [.net 物件導向程式設計進階] (4) 正規表示式 (三) 表示式助手物件程式設計
- 進階7 正規表示式
- Linux系統程式設計(18)——正規表示式實用舉例Linux程式設計
- JavaScript正規表示式進階指南JavaScript
- [.net 物件導向程式設計進階] (3) 正規表示式 (二) 高階應用物件程式設計
- [.net 物件導向程式設計進階] (2) 正規表示式 (一) 快速入門物件程式設計
- 學習C#高階程式設計之正規表示式C#程式設計
- Linux系統程式設計(19)——正規表示式在sed和awk中的使用Linux程式設計
- 正規表示式系列之中級進階篇
- Qt Creator程式設計之正規表示式QT程式設計
- shell程式設計(四)| grep正規表示式程式設計
- shell程式設計(四)| sed 正規表示式程式設計
- 05 shell程式設計之正規表示式程式設計
- Python語法進階(2)- 正規表示式Python
- 【Linux】正規表示式Linux
- 系統認識JavaScript正規表示式JavaScript
- Linux 的正規表示式Linux
- linux grep 正規表示式Linux
- 理解正規表示式(程式設計師第3期文章)程式設計師
- 【Perl程式設計-6】正規表示式--替換+轉化程式設計
- QTP的描述性程式設計與正規表示式QT程式設計
- Linux中使用正規表示式進行文字匹配Linux
- python進階(20) 正規表示式的超詳細使用Python
- 32.企業級開發進階4:正規表示式
- UNIX和LINUX系統的SHELL正規表示式語法(轉)Linux
- Linux中基本正規表示式Linux
- Linux正規表示式詳解Linux
- Shell程式設計基礎學習之一:正規表示式程式設計
- 正規表示式
- [.net 物件導向程式設計進階] (7) Lamda表示式(三) 表示式樹高階應用物件程式設計
- 用正規表示式進行搜尋
- 正規表示式(程式碼java版)Java
- 匹配空行正規表示式程式碼
- Linux grep命令和正規表示式Linux
- Linux正規表示式使用指南Linux
- Linux正規表示式技術指南Linux
- 匹配16進位制顏色正規表示式程式碼