正則是我們日常程式設計中一定會使用到的,不管是各種語言中的正則比對,還是linux/unix系統上的grep/egrep指令,都是在使用正則來比對字元串。随着用的深入,可能會感到越來越迷惑:
為什麼有的語言要提供多種正則比對的函數集?
-- 比如php的preg系列和ereg系列
為什麼有的正則語句在不同的語言上比對出來的東西是不一樣的?
-- 比如unix的grep指令和perl語言的grep
故事從頭開始講
正規表達式(Regular Expression)從1956年就開始出現這個概念,後來Unix之父Ken Tompson将這個概念引入Unix,出現了grep工具。但是随着Unix的版本不斷演化,Unix的差異也越來越大,一統江湖的POSIX标準就此出現。POSIX(Portable Operating System Interface for uniX)提供的是統一的Unix接口,當然也把正則這塊統一了。于是出現了Posix的兩種标準:POSIX Basic Regular Expressions (BRE)和POSIX Extended Regular Expressions(ERE)。
BRE就是現在unix系統使用的grep指令,ERE就是現在unix系統使用的egrep指令。ERE就是BRE的擴充包的意思,基本文法都是一樣的,但是兩者還是有一些差別,比如對于一些特殊符号,“{ }”是否需要使用反斜杆:
要比對“tt”,在BRE中使用“t{1,2}”,在ERE中則是使用“t{1,2}”
Image
PS:現在網絡上說的正則,如果沒有特殊說明,應該都是指的是ERE。它也是現在使用最廣的正則了。
PS2:grep -e就和egrep是一樣的。
故事繼續
如果世界上的正則隻有一種标準,那一切看起來都這麼完美,但是在計算機世界總是有各種各樣的曆史問題。
有很多種語言也自己定義了一套正則标準,雖然大體上和POSIX的這套很像,但總還是有一些不同的細節的。比如Perl,python,Tcl(Tool Command Language)。都有自己定義的一套正則标準。其中Perl的正則到現在演化成為PCRE(Perl Compatible Regular Expressions)。這個正則文法也是被php所采用的。
GNU grep,linux機器上使用最廣泛的正則文法,幾乎所有的linux機器上的grep指令都是GNU grep。它和POSIX是一緻的,有GNU Basic Regular Expressions 和GNU Extends Regular Expressions。
PHP中的正則
PHP中有兩套正則函數集:preg和ereg (如果你算上mb_ereg那就有三套)
preg和ereg分别代表的是PCRE regular Expression和Posix extension regular Expression。preg和ereg有一些不同,最大的不同就是preg有“分隔符”(一般是或者|)來将正規表達式劃出來。還有就是preg是沒有大小寫不同的函數的,它使用“模式修飾符”來對大小寫進行比對。下面是摘自php文檔的函數對照表:
Image(1)
文檔中提到的一個例子需要注意下的:
one(self)?(selfsufficient)? 比對字元串“oneselfsufficient ” 在ereg是會比對出oneselfsufficient的,但是在preg是比對到oneself的。就是說posix會盡可能的比對正則,而對于這種可“多種”比對的正則,pcre的選擇更為保守。
Go中的正則
在函數中也有展現
MustCompile
MustCompilePOSIX
是以呢,下面這個代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import(
)
func main() {
/*
*/
}
z是隻在perl的正則文法存在,表示以t為結尾,在POSIX中沒有,是以如果你把注釋的部分放開,這個程式就會抛出panic