1. 普通字符組
字符組就是一組字符,在正則表達式中,它表示“在同一個位置可能出現的各種字符”,其寫法是在一對方括號[和]之間列出所有可能出現的字符。字符組中的字符排列順序並不影響字符組的功能,出現重複字符也不會影響,所以[0123456789]完全等價於[9876543210]、[1029384756]、[998876543210]。但是並不推薦在字符組中出現重複字符,還應讓字符組中的字符排列更加符合認知習慣。
通過 -範圍表示法 可以進一步簡化字符組,即用[x-y]的形式表示x到y整個範圍內的字符,這樣[0123456789]就可以表示爲[0-9]。在字符組中,-表示的範圍一般是根據字符對應的ASCII編碼來確定,碼值小的字符在前,碼值大的字符在後。在字符組中可以並列多個“-範圍表示法”,字符組[0-9a-zA-Z]可以匹配數字、大寫字母或小寫字母。
2. 元字符與轉義
在上面的字符組中,橫線 - 並不能匹配 - 字符,而是用來表示範圍,這類字符稱爲元字符。字符組的開方括號[、閉方括號]等都算元字符。在匹配中,它們有着特殊的意義。但是有時並不需要表示這種特殊的意義,只需要表示普通字符,此時需要做特殊處理。
對於字符組中的 - ,如果它緊鄰着字符組的開方括號[,那麼它就是普通字符,其它情況下都是元字符;而對於其它元字符,取消特殊含義的做法都是轉義,即在正則表達式中的元字符之前加上反斜線字符\。
如果要在字符組內使用 - ,最好的辦法是將它排列在字符組的開頭。[-09]包含三個字符 - 、0、9;[0-9]包含0 ~ 9這10個字符;[-0-9]包含0 ~ 9和 - 這11個字符。
3. 排除型字符組
排除型字符組非常類似普通字符組,只是在開方括號[之後緊跟一個^ ,寫作[^ ··· ] ,表示在當前位置匹配一個沒有列出的字符。所以[^0-9]就表示0~9之外的字符,也就是非數字字符。
除了開方括號之後的 ^ ,排除型字符組與普通字符組的用法幾乎完全相同。唯一需要改動的是:在排除型字符組中,如果需要表示橫線字符- ,那麼 - 應該緊跟在 ^ 之後;而在普通字符組中,作爲普通字符的橫線 - 應該緊跟在開方括號之後。
在排除型字符組中,^ 是一個元字符,如果想表示 “這個字符組中可以出現 ^ 字符”,不要讓它緊挨着[即可,否則就需要轉義。
4. 字符組簡記法
常見的字符組簡單記法有\d、\w、\s。其中\d等價於[0-9],其中d表示digit;\w等價於[0-9a-zA-Z_],其中w表示word;\s等價於[\t\r\n\v\f],s表示space。注意,\w不僅包含大小寫字母,還包含數字字符和下劃線。字符組簡記法可以單獨出現,也可以使用在字符組中,比如[0-9a-zA-Z]也可以寫作[\da-zA-Z]。同樣也可以用在排除型字符組中。
相對於\d、\w、\s這三個普通字符組簡記法,正則表達式也提供了對應的排除型字符組簡記法\D、\W、\S —— 字母完全一樣,只是改爲大寫。這些簡記法匹配的字符互補:\s能匹配的字符,\S一定不能匹配;\w能匹配的字符,\W一定不能匹配;\d能匹配的字符,\D一定不能匹配。因此,[\s\S]、[\w\W]、[\d\D]這三個都可以匹配任意字符。
注意,如果字符組中出現了字符組簡記法,最好不要出現單獨的 - ,否則就可能引起錯誤,如[\d-a]。此外,以上說的\d、\w、\s的匹配規則,都是針對ASCII編碼而言的,也叫ASCII匹配規則。
5. POSIX字符組
前面介紹的字符組,都屬於Perl衍生出來的正則表達式流派,這個流派叫做PCRE。此外,正則表達式還有其它流派,比如POSIX,它是一系列規範,定義了UNIX操作系統應當支持的功能,其中也包括關於正則表達式的規範。
常見的[a-z]形式的字符組,在POSIX規範中仍然獲得支持,它的準確名稱是POSIX方括號表達式,主要用在UNIX/Linux系統中。POSIX方括號表達式與上述字符組的差別主要在於:在POSIX字符組中,反斜線\不是用來轉義的。所以POSIX方括號表達式[\d]只能匹配\和d兩個字符,而不是[0-9]對應的數字字符。
爲了解決字符組中特殊字符的轉義問題,POSIX方括號表達式規定:如果要在字符組中表達字符],應當讓它緊跟在字符組的開方括號之後,所以[]a]能匹配的字符就是]或a;如果要在字符組中標識字符 - ,就必須將它放在字符組的閉方括號]之前,所以[a-]能匹配的字符就是a或-。
另一方面,POSIX規範還定義了POSIX字符組,它與之前的字符組簡記法類似。下表介紹了POSIX字符組,注意表格中與其對應的是ASCII字符組,也就是能匹配的ASCII字符。因爲POSIX規範中有另一個重要的概念:locale(語言環境),它是一組與語言和文化相關的設定,包括日期格式、貨幣幣值、字符編碼等。POSIX字符組的意義會根據locale的變化而變化,下表介紹的只是這些POSIX字符組在ASCII編碼中的意義;如果換用其它的locale(比如使用Unicode字符集),它們的意義可能會發生變化。
POSIX 字符組 | 說明 | ASCII 字符組 | 等價的 PCRE 簡記法 |
---|---|---|---|
[:alnum:]* | 字母字符和數字字符 | [0-9a-zA-Z] | |
[:alpha:] | 字母 | [a-zA-Z] | |
[:ASCII:] | ASCII字符 | [\x00-\x7F] | |
[:blank:] | 空格和製表符 | [ \t] | |
[:cntrl:] | 控制字符 | [\x00-\x1F\x7F] | |
[:digit:] | 數字字符 | [0-9] | \d |
[:graph:] | 空白字符之外的字符 | [\x21-\x7E | |
[:lower:] | 小寫字母字符 | [a-z] | |
[:print:] | 類似[:graph:],但包括空白字符 | [\x20-\x7E] | |
[:punct:] | 標點符號 | [][!"#$%&’()*+,./:;<=>?@^_`{|}~-] | |
[:space:] | 空白字符 | [ \t\r\n\v\f] | \s |
[:upper:] | 大寫字母字符 | [A-Z] | |
[:word:]* | 字母字符 | [A-Za-z0-9_] | \w |
[:xdigit:] | 十六進制字符 | [A-Fa-f0-9] |
其中標記*的字符簡記法並不是POSIX規範中的,但使用比較多,一般語言中都提供。
POSIX字符組簡記法的使用也與PCRE字符組簡記法有所不同,主要區別在於,PCRE字符組簡記法可以脫離方括號直接出現,而POSIX字符組必須出現在方括號內。