正则是我们日常编程中一定会使用到的,不管是各种语言中的正则匹配,还是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}”

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中有两套正则函数集:preg和ereg (如果你算上mb_ereg那就有三套)
preg和ereg分别代表的是pcre regular expression和posix extension regular expression。preg和ereg有一些不同,最大的不同就是preg有“分隔符”(一般是\或者|)来将正则表达式划出来。还有就是preg是没有大小写不同的函数的,它使用“模式修饰符”来对大小写进行匹配。下面是摘自php文档的函数对照表:
文档中提到的一个例子需要注意下的:
one(self)?(selfsufficient)? 匹配字符串“oneselfsufficient ” 在ereg是会匹配出oneselfsufficient的,但是在preg是匹配到oneself的。就是说posix会尽可能的匹配正则,而对于这种可“多种”匹配的正则,pcre的选择更为保守。
go中的正则包是regexp,它使用的是叫做re2(https://code.google.com/p/re2/wiki/syntax)这个c++写的库,这个库支持了两种标准:perl 和 posix
在函数中也有体现
mustcompile
mustcompileposix
所以呢,下面这个代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<code>package main</code>
<code>import(</code>
<code> </code><code>"regexp"</code>
<code> </code><code>"fmt"</code>
<code>)</code>
<code>func main() {</code>
<code> </code><code>var</code> <code>origin1 = `tt`</code>
<code> </code><code>var</code> <code>reg = `t\z`</code>
<code> </code><code>matches1 := regexp.mustcompile(reg).findstring(origin1)</code>
<code> </code><code>fmt.println(matches1)</code>
<code>/*</code>
<code> </code><code>matches2 := regexp.mustcompileposix(reg).findstring(origin1)</code>
<code> </code><code>fmt.println(matches2)</code>
<code>*/</code>
<code>}</code>
\z是只在perl的正则语法存在,表示以t为结尾,在posix中没有,所以如果你把注释的部分放开,这个程序就会抛出panic