正則表示式——POSIX字元組
前面介紹了常用的字元組,但是在某些文件中,你可能會發現類似[:digit:]、[:lower:]之類的字元組,看起來不難理解(digit就是"數字",lower就是"小寫"),但又很奇怪,它們就是POSIX字元組(POSIX Character Class)。因為某些語言的文件中出現了這些字元組,為避免困惑,這裡有必要做個簡要介紹。如果只使用常用的程式語言,可以忽略文件中的POSIX字元組,也可以忽略本節;如果想了解POSIX字元組,或者需要在Linux/UNIX下的各種工具(sed、awk、grep等)中使用正則表示式,最好閱讀本節。
之前介紹的字元組,都屬於Perl衍生出來的正則表示式流派(Flavor),這個流派叫做PCRE(Per Compatible Regular Expression)。在此之外,正則表示式還有其他流派,比如POSIX(Portable Operating System Interface for uniX),它是一系列規範,定義了UNIX作業系統應當支援的功能,其中也包括關於正則表示式的規範,[:digit:]之類的字元組就是遵循POSIX規範的字元組。
常見的[a-z]形式的字元組,在POSIX規範中仍然獲得支援,它的準確名稱是POSIX方括號表示式(POSIX bracket expression),主要用在UNIX/Linux系統中。POSIX方括號表示式與之前所說的字元組最主要的差別在於:在POSIX字元組中,反斜線\不是用來轉義的。所以POSIX方括號表示式[\d]只能匹配\和d兩個字元,而不是[0-9]對應的數字字元。
為了解決字元組中特殊意義字元的轉義問題,POSIX方括號表示式規定:如果要在字元組中表達字元](而不是作為字元組的結束標記),應當讓它緊跟在字元組的開方括號之後,所以[]a]能匹配的字元就是]或a;如果要在字元組中標識字元-(而不是"-範圍表示法"),就必須將它放在字元組的閉方括號]之前,所以[a-]能匹配的字元就是a或-。
另一方面,POSIX規範還定義了POSIX字元組(POSIX character class),它大致等於之前介紹的字元組簡記法,都是使用類似[:digit:]、[:lower:]之類有明確意義的記號表示某類字元。
表1-2簡要介紹了POSIX字元組,注意表格中與其對應的是ASCII字元組,也就是能匹配的ASCII字元(ASCII編碼表中碼值在0~127之間的字元)。因為POSIX規範中有一個重要概念:locale(通常翻譯為"語言環境"),它是一組與語言和文化相關的設定,包括日期格式、貨幣幣值、字元編碼等。POSIX字元組的意義會根據locale的變化而變化,表1-2介紹的只是這些POSIX字元組在ASCII編碼中的意義;如果換用其他的locale(比如使用Unicode字符集),它們的意義可能會發生變化,具體請參考第129頁。
表1-2 POSIX字元組
POSIX字元組 |
說明 |
ASCII字元組 |
等價的PCRE 簡記法 |
[:alnum:]* |
字母字元和數字字元 |
[a-zA-Z0-9] |
|
[:ASCII:] |
ASCII字元 |
[\x00-\x7F] |
|
[:alpha:] |
字母 |
[a-zA-Z] |
|
[:blank:] |
空格字元和 製表符 |
[ \t] |
|
[:cntrl:] |
控制字元 |
[\x00-\x1F\x7F] |
|
[:digit:] |
數字字元 |
[0-9] |
\d |
[:graph:] |
空白字元之 外的字元 |
[\x21-\x7E] |
|
[:lower:] |
小寫字母字元 |
[a-z] |
|
[:print:] |
類似[:graph:],但包括空白字元 |
[\x20-\x7E] |
|
[:punct:] |
標點符號 |
[][!"#$%&'()*+,./:;<=>[email protected]\^_`{|}~-] |
|
[: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字元組必須出現在方括號內。所以同樣是匹配數字字元,PCRE中可以直接寫\d,而POSIX字元組必須寫成[[:digit:]]。
在本書介紹的6種語言中,Java、PHP、Ruby支援使用POSIX字元組。
在PHP中可以直接使用POSIX字元組,但是PHP中的POSIX字元組只識別ASCII字元,也就是說,任何非ASCII字元(比如中文字元)都不能由任何一個POSIX字元組匹配。
Ruby的情況稍微複雜一點。Ruby 1.8中的POSIX字元組只能匹配ASCII字元,而且不支援[:word:]和[:ASCII:];Ruby 1.9中的POSIX字元組可以匹配Unicode字元,而且支援[:word:]和[:ASCII:]。
Java中的情況更加複雜。POSIX字元組[[:name:]]必須使用\p{name}的形式,其中name為POSIX字元組對應的名字,比如[:space:]就應當寫作\p{Space},請注意第一個字母要大寫,其他POSIX字元組都是這樣,只有[:xdigit:]要寫作\p{XDigit}。並且Java中的POSIX字元組,只能匹配ASCII字元。