PHP Perl兼容正则表达式 和 POSIX扩展表达式
2009年02月25日 星期三 上午 11:42
[^xyz] 字符的补集,除xyz之外的字符
^-?[0-9]*.?[0-9]*$ 所有小树
通用字符簇:
[[:alpha:]] 任何字母
[[:digit:]] 任何数字
============
    常用的正则表达式
    1、非负整数:”^\d+$”
    2、正整数:”^[0-9]*[1-9][0-9]*$”
    3、非正整数:”^((-\d+)|(0+))$”
    4、负整数:”^-[0-9]*[1-9][0-9]*$”
    5、整数:”^-?\d+$”
    6、非负浮点数:”^\d+(\.\d+)?$”
    7、正浮点数:”^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$”
    8、非正浮点数:”^((-\d+\.\d+)?)|(0+(\.0+)?))$”
    9、负浮点数:”^(-((正浮点数正则式)))$”
    10、英文字符串:”^[A-Za-z]+$”
    11、英文大写串:”^[A-Z]+$”
    12、英文小写串:”^[a-z]+$”
    13、英文字符数字串:”^[A-Za-z0-9]+$”
    14、英数字加下划线串:”^\w+$”
    15、E-mail地址:”^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$”
    16、URL:”^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$”
=============
Perl和POSIX表达式的写法区别
preg    ereg
\d+    [0-9]*
[abc\d+]    abc[0-9]*    //perl中字符都要加上分隔符[]或()或||
\w     [A-Za-z0-9_]
[log]$i    ereg中模式修正符i,m,s等无效,所以最接近的表达式是: log$
perl中字符串必须包含在[],()之间或是紧邻^、$
============
preg_grep

(PHP 4, PHP 5)

preg_grep — 返回与模式匹配的数组单元
说明
array preg_grep ( string $pattern , array $input [, int $flags ] )

preg_grep() 返回一个数组,其中包括了 input 数组中与给定的 pattern 模式相匹配的单元。

flags 可以是以下标记:

PREG_GREP_INVERT
    如果传递入此标记,preg_grep() 会返回输入数组中不匹配给定 pattern 的单元。本标记自 PHP 4.2.0 起可用。

自 PHP 4.0.4 起,preg_grep() 返回的结果使用从输入数组来的键名进行索引。如果不希望这样的结果,用 array_values() 对 preg_grep() 返回的结果重新索引。

Example#1 preg_grep() 例子
<?php
// return all array elements
// containing floating point numbers
$fl_array = preg_grep ("/^(\d+)?\.\d+$/", $array);
?>

==================================
ereg_replace
(PHP 4, PHP 5)

ereg_replace — 正则表达式替换

说明
string ereg_replace ( string $pattern , string $replacement , string $string )
本函数在 string 中扫描与 pattern 匹配的部分,并将其替换为 replacement 。

返回替换后的字符串。(如果没有可供替换的匹配项则会返回原字符串。)

如果 pattern 包含有括号内的子串,则 replacement 可以包含形如 \\digit 的子串,这些子串将被替换为数字表示的的第几个括号内的子串;\\0 则包含了字符串的整个内容。最多可以用九个子串。括号可以嵌套,此情形下以左圆括号来计算顺序。

如果未在 string 中找到匹配项,则 string 将原样返回。

例如,下面的代码片断输出 "This was a test" 三次:


Example#1 ereg_replace() 例子

<?php
$string = "This is a test";
echo str_replace(" is", " was", $string);
echo ereg_replace("( )is", "\\1was", $string);
echo ereg_replace("(( )is)", "\\2was", $string);
?>

要注意的一点是如果在 replacement 参数中使用了整数值,则可能得不到所期望的结果。这是因为 ereg_replace() 将把数字作为字符的序列值来解释并应用之。例如:


Example#2 ereg_replace() 例子

<?php
/* 不能产生出期望的结果 */
$num = 4;
$string = "This string has four words.";
$string = ereg_replace('four', $num, $string);
echo $string;   /* Output: 'This string has   words.' */

/* 本例工作正常 */
$num = '4';
$string = "This string has four words.";
$string = ereg_replace('four', $num, $string);
echo $string;   /* Output: 'This string has 4 words.' */
?>


Example#3 将 URL 替换为超连接

<?php
$text = ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]",
                     "<a href=\"\\0\">\\0</a>", $text);
?>

Tip
preg_replace() 函数使用了 Perl 兼容正则表达式语法,通常是比 ereg_replace() 更快的替代方案。


===========================================

模式修正符
(No version information available, might be only in CVS)

模式修正符 — 解说正则表达式模式中使用的修正符

说明
下面列出了当前在 PCRE 中可能使用的修正符。括号中是这些修正符的内部 PCRE 名。修正符中的空格和换行被忽略,其它字符会导致错误。


i (PCRE_CASELESS)
如果设定此修正符,模式中的字符将同时匹配大小写字母。
m(PCRE_MULTILINE)
默认情况下,PCRE 将目标字符串作为单一的一“行”字符所组成的(甚至其中包含有换行符也是如此)。“行起始”元字符(^)仅仅匹配字符串的起始,“行结束”元字符($)仅 仅匹配字符串的结束,或者最后一个字符是换行符时其前面(除非设定了 D 修正符)。这和 Perl 是一样的。当设定了此修正符,“行起始”和“行结束”除了匹配整个字符串开头和结束外,还分别匹配其中的换行符的之后和之前。这和 Perl 的 /m 修正符是等效的。如果目标字符串中没有“\n”字符或者模式中没有 ^ 或 $,则设定此修正符没有任何效果。
s(PCRE_DOTALL)
如果设定了此修正符,模式中的圆点元字符(.)匹配所有的字符,包括换行符。没有此设定的话,则不包括换行符。这和 Perl 的 /s 修正符是等效的。排除字符类例如 [^a] 总是匹配换行符的,无论是否设定了此修正符。
x(PCRE_EXTENDED)
如果设定了此修正符,模式中的空白字符除了被转义的或在字符类中的以外完全被忽略,在未转义的字符类之外的 # 以及下一个换行符之间的所有字符,包括两头,也都被忽略。这和 Perl 的 /x 修正符是等效的,使得可以在复杂的模式中加入注释。然而注意,这仅适用于数据字符。空白字符可能永远不会出现于模式中的特殊字符序列,例如引入条件子模式 的序列 (?( 中间。
e
如果设定了此修正符,preg_replace() 在替换字符串中对逆向引用作正常的替换,将其作为 PHP 代码求值,并用其结果来替换所搜索的字符串。
只有 preg_replace() 使用此修正符,其它 PCRE 函数将忽略之。

Note: 本修正符在 PHP3 中不可用。


A(PCRE_ANCHORED)
如果设定了此修正符,模式被强制为“anchored”,即强制仅从目标字符串的开头开始匹配。此效果也可以通过适当的模式本身来实现(在 Perl 中实现的唯一方法)。
D(PCRE_DOLLAR_ENDONLY)
如果设定了此修正符,模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,美元符号也会匹配此字符之前(但不会匹配任何其它换行符之前)。如果设定了 m 修正符则忽略此选项。Perl 中没有与其等价的修正符。
S
当一个模式将被使用若干次时,为加速匹配起见值得先对其进行分析。如果设定了此修正符则会进行额外的分析。目前,分析一个模式仅对没有单一固定起始字符的 non-anchored 模式有用。
U(PCRE_UNGREEDY)
本修正符反转了匹配数量的值使其不是默认的重复,而变成在后面跟上“?”才变得重复。这和 Perl 不兼容。也可以通过在模式之中设定 (?U) 修正符或者在数量符之后跟一个问号(如 .*?)来启用此选项。
X(PCRE_EXTRA)
此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式中的任何反斜线后面跟上一个没有特殊意义的字母导致一个错误,从而保留此组合以备将来扩充。默认情况下,和 Perl 一样,一个反斜线后面跟一个没有特殊意义的字母被当成该字母本身。当前没有其它特性受此修正符控制。
u(PCRE_UTF8)
此修正符启用了一个 PCRE 中与 Perl 不兼容的额外功能。模式字符串被当成 UTF-8。本修正符在 Unix 下自 PHP 4.1.0 起可用,在 win32 下自 PHP 4.2.3 起可用。自 PHP 4.3.5 起开始检查模式的 UTF-8 合法性。


========================
preg_split
(PHP 4, PHP 5)

preg_split — 用正则表达式分割字符串

说明
array preg_split ( string $pattern , string $subject [, int $limit [, int $flags ]] )
返回一个数组,包含 subject 中沿着与 pattern 匹配的边界所分割的子串。

如果指定了 limit ,则最多返回 limit 个子串,如果 limit 是 -1,则意味着没有限制,可以用来继续指定可选参数 flags 。

flags 可以是下列标记的任意组合(用按位或运算符 | 组合):

PREG_SPLIT_NO_EMPTY
如果设定了本标记,则 preg_split() 只返回非空的成分。
PREG_SPLIT_DELIM_CAPTURE
如果设定了本标记,定界符模式中的括号表达式也会被捕获并返回。本标记添加于 PHP 4.0.5。
PREG_SPLIT_OFFSET_CAPTURE
如果设定了本标记,如果设定本标记,对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值,使其中的每个单元也是一个数组,其中第一项为匹配字符串,第二项为其在 subject 中的偏移量。本标记自 PHP 4.3.0 起可用。


Tip
如果不需要正则表达式的功能,可以选择使用更快(也更简单)的替代函数如 explode() 或 str_split()。


Example#1 preg_split() 例子:取得搜索字符串的成分

<?php
// split the phrase by any number of commas or space characters,
// which include " ", \r, \t, \n and \f
$keywords = preg_split ("/[\s,]+/", "hypertext language, programming");
?>


Example#2 将字符串分割成字符

<?php
$str = 'string';
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
?>


Example#3 将字符串分割为匹配项及其偏移量

<?php
$str = 'hypertext language programming';
$chars = preg_split('/ /', $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
print_r($chars);
?>
本例将输出:

Array
(
    [0] => Array
        (
            [0] => hypertext
            [1] => 0
        )

    [1] => Array
        (
            [0] => language
            [1] => 10
        )

    [2] => Array
        (
            [0] => programming
            [1] => 19
        )

)

   
Note: flags 是 PHP 4 Beta 3 添加的。



===========================
preg_replace_callback
(PHP 4 >= 4.0.5, PHP 5)

preg_replace_callback — 用回调函数执行正则表达式的搜索和替换

说明
mixed preg_replace_callback ( mixed $pattern , callback $callback , mixed $subject [, int $limit ] )
本函数的行为几乎和 preg_replace() 一样,除了不是提供一个 replacement 参数,而是指定一个 callback 函数。该函数将以目标字符串中的匹配数组作为输入参数,并返回用于替换的字符串。

Example#1 preg_replace_callback() 例子

<?php
// 此文本是用于 2002 年的,
// 现在想使其能用于 2003 年
$text = "April fools day is 04/01/2002\n";
$text.= "Last christmas was 12/24/2001\n";

// 回调函数
function next_year($matches) {
    // 通常:$matches[0] 是完整的匹配项
    // $matches[1] 是第一个括号中的子模式的匹配项
    // 以此类推
    return $matches[1].($matches[2]+1);
}

echo preg_replace_callback(
              "|(\d{2}/\d{2}/)(\d{4})|",
              "next_year",
              $text);

// 结果为:
// April fools day is 04/01/2003
// Last christmas was 12/24/2002
?>

Example#2 preg_replace_callback() 和 create_function()

<?php
/* 一个 UNIX 风格的命令行过滤器,将每个段落开头的
   * 大写字母转换成小写字母 */

$fp = fopen("php://stdin", "r") or die("can't read stdin");
while (!feof($fp)) {
      $line = fgets($fp);
      $line = preg_replace_callback(
          '|<p>\s*\w|',
          create_function(
              // 这里使用单引号很关键,
              // 否则就把所有的 $ 换成 \$
              '$matches',
              'return strtolower($matches[0]);'
          ),
          $line
      );
      echo $line;
}
fclose($fp);
?>


==========================
flags 可以是以下标记:

PREG_GREP_INVERT
如果传递入此标记,preg_grep() 会返回输入数组中不匹配给定 pattern 的单元。本标记自 PHP 4.2.0 起可用。

自 PHP 4.0.4 起,preg_grep() 返回的结果使用从输入数组来的键名进行索引。如果不希望这样的结果,用 array_values() 对 preg_grep() 返回的结果重新索引。


Example#1 preg_grep() 例子

<?php
// return all array elements
// containing floating point numbers
$fl_array = preg_grep ("/^(\d+)?\.\d+$/", $array);
?>
================================
preg_match
(PHP 4, PHP 5)

preg_match — 进行正则表达式匹配

说明
int preg_match ( string $pattern , string $subject [, array $matches [, int $flags ]] )
在 subject 字符串中搜索与 pattern 给出的正则表达式相匹配的内容。

如果提供了 matches ,则其会被搜索的结果所填充。$matches[0] 将包含与整个模式匹配的文本,$matches[1] 将包含与第一个捕获的括号中的子模式所匹配的文本,以此类推。

flags 可以是下列标记:

PREG_OFFSET_CAPTURE
如果设定本标记,对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值,使其中的每个单元也是一个数组,其中第一项为匹配字符串,第二项为其偏移量。本标记自 PHP 4.3.0 起可用。
flags 参数自 PHP 4.3.0 起可用。

preg_match() 返回 pattern 所匹配的次数。要么是 0 次(没有匹配)或 1 次,因为 preg_match() 在第一次匹配之后将停止搜索。preg_match_all() 则相反,会一直搜索到 subject 的结尾处。如果出错 preg_match() 返回 FALSE。

Tip
如果只想查看一个字符串是否包含在另一个字符串中,不要用 preg_match()。可以用 strpos() 或 strstr() 替代,要快得多。


Example#1 在文本中搜索“php”

<?php
// 模式定界符后面的 "i" 表示不区分大小写字母的搜索
if (preg_match ("/php/i", "PHP is the web scripting language of choice.")) {
    print "A match was found.";
} else {
    print "A match was not found.";
}
?>


Example#2 搜索单词“web”

<?php
/* 模式中的 \b 表示单词的边界,因此只有独立的 "web" 单词会被匹配,
* 而不会匹配例如 "webbing" 或 "cobweb" 中的一部分 */
if (preg_match ("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
    print "A match was found.";
} else {
    print "A match was not found.";
}

if (preg_match ("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
    print "A match was found.";
} else {
    print "A match was not found.";
}
?>


Example#3 从 URL 中取出域名

<?php
// 从 URL 中取得主机名
preg_match("/^(http:\/\/)?([^\/]+)/i",
    "http://www.php.net/index.html", $matches);
$host = $matches[2];

// 从主机名中取得后面两段
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>
本例将输出:

domain name is: php.net


========================
preg_match_all
(PHP 4, PHP 5)

preg_match_all — 进行全局正则表达式匹配

说明
int preg_match_all ( string $pattern , string $subject , array $matches [, int $flags ] )
在 subject 中搜索所有与 pattern 给出的正则表达式匹配的内容并将结果以 flags 指定的顺序放到 matches 中。

搜索到第一个匹配项之后,接下来的搜索从上一个匹配项末尾开始。

flags 可以是下列标记的组合(注意把 PREG_PATTERN_ORDER 和 PREG_SET_ORDER 合起来用没有意义):

PREG_PATTERN_ORDER
对结果排序使 $matches[0] 为全部模式匹配的数组,$matches[1] 为第一个括号中的子模式所匹配的字符串组成的数组,以此类推。


<?php
preg_match_all ("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_PATTERN_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>
本例将输出:

<b>example: </b>, <div align=left>this is a test</div>
example: , this is a test

          因此,$out[0] 包含匹配整个模式的字符串,$out[1] 包含一对 HTML 标记之间的字符串。


PREG_SET_ORDER
对结果排序使 $matches[0] 为第一组匹配项的数组,$matches[1] 为第二组匹配项的数组,以此类推。

<?php
preg_match_all ("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_SET_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>
本例将输出:

<b>example: </b>, example:
<div align=left>this is a test</div>, this is a test

         
本例中,$matches[0] 是第一组匹配结果,$matches[0][0] 包含匹配整个模式的文本,$matches[0][1] 包含匹配第一个子模式的文本,以此类推。同样,$matches[1] 是第二组匹配结果,等等。

PREG_OFFSET_CAPTURE
如果设定本标记,对每个出现的匹配结果也同时返回其附属的字符串偏移量。注意这改变了返回的数组的值,使其中的每个单元也是一个数组,其中第一项为匹配字符串,第二项为其在 subject 中的偏移量。本标记自 PHP 4.3.0 起可用。


如果没有给出标记,则假定为 PREG_PATTERN_ORDER。

返回整个模式匹配的次数(可能为零),如果出错返回 FALSE。


Example#1 从某文本中取得所有的电话号码

<?php
preg_match_all ("/\(? (\d{3})? \)? (?(1) [\-\s] ) \d{3}-\d{4}/x",
                "Call 555-1212 or 1-800-555-1212", $phones);
?>


Example#2 搜索匹配的 HTML 标记(greedy)

<?php
// \\2 是一个逆向引用的例子,其在 PCRE 中的含义是
// 必须匹配正则表达式本身中第二组括号内的内容,本例中
// 就是 ([\w]+)。因为字符串在双引号中,所以需要
// 多加一个反斜线。
$html = "<b>bold text</b><a href=howdy.html>click me</a>";

preg_match_all ("/(<([\w]+)[^>]*>)(.*)(<\/\\2>)/", $html, $matches);

for ($i=0; $i< count($matches[0]); $i++) {
echo "matched: ".$matches[0][$i]."\n";
echo "part 1: ".$matches[1][$i]."\n";
echo "part 2: ".$matches[3][$i]."\n";
echo "part 3: ".$matches[4][$i]."\n\n";
}
?>
本例将输出:

matched: <b>bold text</b>
part 1: <b>
part 2: bold text
part 3: </b>

matched: <a href=howdy.html>click me</a>
part 1: <a href=howdy.html>
part 2: click me
part 3: </a>

==============================
preg_replace
字符串比对解析并取代。

语法: mixed preg_replace(mixed pattern, mixed replacement, mixed subject);

返回值: 混合类型资料

函数种类: 资料处理
内容说明
本函数以 pattern 的规则来解析比对字符串 subject,欲取而代之的字符串为参数 replacement。返回值为混合类型资料,为取代后的字符串结果。

使用范例
下例返回值为 $startDate = 6/19/1969

<?php
$patterns = array("/(19|20\d{2})-(\d{1,2})-(\d{1,2})/", "/^\s*{(\w+)}\s*=/");
$replace = array("\\3/\\4/\\1", "$\\1 =");
print preg_replace($patterns, $replace, "{startDate} = 1969-6-19");
?>


=============================
PHP正则表达式使用详解

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
    可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式,即/expression/

    普通字符

    由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。
    非打印字符

    字符       含义

    \cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
    \f 匹配一个换页符。等价于 \x0c 和 \cL。
    \n 匹配一个换行符。等价于 \x0a 和 \cJ。
    \r 匹配一个回车符。等价于 \x0d 和 \cM。
    \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
    \S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
    \t 匹配一个制表符。等价于 \x09 和 \cI。
    \v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
    正则表达式中的特殊字符

    所谓特殊字符,就是一些有特殊含义的字符,如上面说的"*.txt"中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个\。ls \*.txt。正则表达式有以下特殊字符。
    特别字符 说明

    $ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
    ( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
    * 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
    + 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
    . 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。
    [ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
    ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
    \ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
    ^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
    { 标记限定符表达式的开始。要匹配 {,请使用 \{。
    | 指明两项之间的一个选择。要匹配 |,请使用 \|。
    构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
    限定符

    限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。
    *、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。
    正则表达式的限定符有:
    字符 描述

    * 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
    + 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
    ? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
    {n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
    {n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
    {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
    定位符

    用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,\b描述单词的前或后边界,\B表示非单词边界。不能对定位符使用限定符。
    选择

    用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。
    其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
    后向引用

    对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容 存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
    可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对相关匹配的保存。

======================
模式语法
(No version information available, might be only in CVS)

模式语法 — 解说 Perl 兼容正则表达式的语法

说明
PCRE 库是一组用和 Perl 5 相同的语法和语义实现了正则表达式模式匹配的函数,不过有少许区别(见下面)。当前 PCRE 的实现是与 Perl 5.005 相符的。

与 Perl 的区别
这里谈到的区别是就 Perl 5.005 来说的。

默认情况下,空白字符是 C 语言库函数 isspace() 所能识别的任何字符,尽管有可能与别的字符类型表编译在一起。通常 isspace() 匹配空格,换页符,换行符,回车符,水平制表符和垂直制表符。Perl 5 不再将垂直制表符包括在空白字符中了。事实上长久以来存在于 Perl 文档中的转义序列 \v 从未被识别过,不过该字符至少到 5.002 为止都被当成空白字符的。在 5.004 和 5.005 中 \s 不匹配此字符。
PCRE 不允许在向前断言中使用重复的数量符。Perl 允许这样,但可能不是你想象中的含义。例如,(?!a){3} 并不是断言下面三个字符不是“a”,而是断言下一个字符不是“a”三次。
捕获出现在排除模式断言中的子模式虽然被计数,但并未在偏移向量中设定其条目。Perl 在匹配失败前从此种模式中设定其数字变量,但只在排触摸式断言只包含一个分支时。
尽管目标字符串中支持二进制的零字符,但不能出现在模式字符串中,因为它被当作普通的 C 字符串传递,以二进制零终止。转义序列“\x00”可以在模式中用来表示二进制零。
不支持下列 Perl 转义序列:\l,\u,\L,\U。事实上这些是由 Perl 的字符串处理来实现的,并不是模式匹配引擎的一部分。
不支持 Perl 的 \G 断言,因为这和单个的模式匹配无关。
很明显,PCRE 不支持 (?{code}) 结构。
当部分模式重复的时候,有关 Perl 5.005_02 捕获字符串的设定有些古怪的地方。举例说,用模式 /^(a(b)?)+$/ 去匹配 "aba" 会将 $2 设为 "b",但是用模式 /^(aa(bb)?)+$/ 去匹配 "aabbaa" 会使 $2 无值。然而,如果把模式改成 /^(aa(b(b))?)+$/,则 $2(和 $3)就有值了。在 Perl 5.004 中以上两种情况下 $2 都会被赋值,在 PCRE 中也是 TRUE。如果以后 Perl 改了,PCRE 可能也会跟着改。
另一个未解决的矛盾是 Perl 5.005_02 中模式 /^(a)?(?(1)a|b)+$/ 能匹配上字符串 "a",但是 PCRE 不会。然而,在 Perl 和 PCRE 中用 /^(a)?a/ 去匹配 "a" 会使 $1 没有值。
PCRE 提供了一些对 Perl 正则表达式机制的扩展:

尽管向后断言必须匹配固定长度字符串,但每个向后断言的分支可以匹配不同长度的字符串。Perl 5.005 要求所有分支的长度相同。
如果设定了 PCRE_DOLLAR_ENDONLY 而没有设定 PCRE_MULTILINE,则 $ 元字符只匹配字符串的最末尾。
如果设定了 PCRE_EXTRA,反斜线后面跟一个没有特殊含义的字母会出错。
如果设定了 PCRE_UNGREEDY,则重复的数量符的 greed 被反转,即,默认时不是 greedy,但如果后面跟上一个问号就变成 greedy 了。


子模式
子模式由圆括号定界,可以嵌套。将模式中的一部分标记为子模式可以:

1. 将多选一的分支局部化。例如,模式:

       cat(aract|erpillar|)

    匹配了 "cat","cataract" 或 "caterpillar" 之一,没有圆括号的话将匹配 "cataract","erpillar" 或空字符串。

2. 将子模式设定为捕获子模式(如同以前定义的)。当整个模式匹配时,目标字符串中匹配了子模式的部分会通过 pcre_exec() 的 ovector 参数传递回调用者。左圆括号从左到右计数(从 1 开始)以取得捕获子模式的数目。

例如,如果将字符串 "the red king" 来和模式

       the ((red|white) (king|queen))

    进行匹配,捕获的子串为 "red king","red" 以及 "king",并被计为 1,2 和 3。

简单的括号实现两种功能的事实不总是有帮助的。经常有需要一组子模式但不需要捕获的时候。如果左括号后面跟着 "?:",子模式不做任何捕获,并且在计算任何之后捕获的子模式时也不算在内。例如,如果用字符串 "the white queen" 去和模式 the ((?:red|white) (king|queen)) 匹配,捕获的子串是 "white queen" 和 "queen",并被计为 1 和 2。所捕获的子串的最大数目是 99,所有子模式,包括捕获的和没捕获的,最大数目是 200。

作为方便的速记,如果在非捕获子模式的开头需要任何选项设定,则选项字母可以出现在 "?" 和 ":" 中间。因此下面两个模式

       (?i:saturday|sunday)
       (?:(?i)saturday|sunday)
   匹配了完全相同的一组字符串。因为分支选项是从左向右尝试的,并且直到子模式结束前都不会重置选项,因此在一个分支中的选项设定会影响到之后的分支,所以以上模式会匹配 "SUNDAY" 和 "Saturday"。

自 PHP 4.3.3 起有可能通过 (?P<name>pattern) 来给一个模式命名。匹配结果的数组会同时包含以模式名为索引和以数字为索引的部分。

重复
重复是由数量符指定的,可以接以下任何一项:

单个字符,可以是被转义的
. 匹配字符
一类字符
一个反向引用(见下一节)
一个括号中的子模式(除非是个断言 - 见下)

普通的重复数量符指定了所允许的匹配的最小和最大数目,方法是将两个数字放在花括号中,中间用逗号分隔。数字必须小于 65536,并且第一个数字必须小于或等于第二个数字。例如:z{2,4} 匹配了 "zz","zzz" 或 "zzzz"。单个的右花括号不算是特殊字符。如果省略了第二个数字但是有逗号,则表示没有上限。如果同时省略了第二个数字和逗号,则数量符指定了匹配的 准确数目。因此 [aeiou]{3,} 匹配至少连续 3 个元音,但是可以匹配更多。\d{8} 则匹配了正好 8 个数字。出现在不允许放置数量符位置或者不符合数量符语法的左花括号,被当成字面上的该字符。例如 {,6} 不是一个数量符,而是字面上的这四个字符。

数量符 {0} 是允许的,导致表达式理解为前一项和数量符不存在。

为方便起见(以及历史性的兼容),三个最常用的数量符都有单字符的缩写: 单字符数量符 * 等同于 {0,}
+ 等同于 {1,}
? 等同于 {0,1}


有可能通过在一个不匹配任何字符的子模式后面跟一个没有上限的数量符构造出无限循环,例如:(a?)*。

对此类模式早期版本的 Perl 和 PCRE 会在编译时给出错误。不过由于这在某些情况下有用,如今已经接受此种模式了,但是如果任何子模式的重复确实不匹配任何字符,则循环会被强制打断。

默认时,数量符是“贪吃型”(greedy)的,即会在不导致剩余模式失败的情况下尽可能多地匹配(直到所允许的数目上限)。这会出问题的经典例子是尝试 匹配 C 语言的注释。在 /* 和 */ 序列中间,可能会出现单个的 * 和 / 字符。对 C 注释如果试图用 /\*.*\*/ 去和字符串 /* first comment */ not comment /* second comment */ 匹配会失败,因为由于 .* 项目的贪吃性,会匹配成整个字符串。

不过,如果在后面加一个问号数量符,则会停止贪吃性,而变成匹配尽可能少的数目,因此模式 /\*.*?\*/ 就会正确匹配 C 注释。各种数量符的含义并没有改变,只是优先的匹配数目。不要将问号的此用法和其自己作为数量符的使用混淆。因为有两种用法,有时可以两个一起出现,例如 \d??\d 会优先匹配一个数字,但如别无选择也可以匹配两个以使剩余模式匹配。

如果设定了 PCRE_UNGREEDY 选项(此选项 Perl 中没有)则数量符默认不是贪吃型的,但是在个别模式后加上一个问号可以将其变成贪吃型的。换句话说,这可以反转默认的行为。

后面跟上一个 + 的数量符是“占有性”(possessive)的。它会匹配尽可能多的字符而不管剩余的模式。因此 .*abc 可以匹配 "aabc" 但是 .*+abc 就不会,因为 .*+ 已经匹配了整个字符串。自 PHP 4.3.3 起可以用占有性数量符可以来加快处理过程。

注释
序列 (?# 标记了注释的开头直到下一个右括号为止。不允许嵌套注释。注释在模式匹配中完全没有作用。

如果设定了 PCRE_EXTENDED 选项,则不在字符类中间并且未转义的 # 字符标记了注释的开头,直到模式中的下一个换行符结束。

===================================
POSIX 扩展正则表达式函数
简介
Tip
PHP 也支持使用 Perl 兼容语法的 PCRE 函数,支持 non-greedy 匹配,断言,条件子模式以及其它许多 POSIX 扩展正则表达式语法所不支持的特性。

Warning
本类正则表达式并不能安全用于二进制模式。PCRE 函数则可以。

正则表达式在 PHP 中用来做复杂的字符串操作。PHP 使用 POSIX 扩展的正则表达式,其由 POSIX 1003.2 定义。对于 POSIX 正则表达式完整的说明见 » regex 手册页,位于 PHP 发布包中的 regex 目录下。这是 UNIX 下的手册格式,需要用类似如下命令 man /usr/local/src/regex/regex.7 来阅读。

需求
要编译本扩展模块无需外部库文件。

安装
Warning
除非知道自己在做什么,否则不要改变 TYPE。

要激活 regexp 的支持在配置 PHP 时加上 --with-regex[=TYPE]。TYPE 可以是 system,apache 或 php 之一。默认使用 php。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置
本扩展模块在 php.ini 中未定义任何配置选项。

资源类型
本扩展模块未定义任何资源类型。

预定义常量
本扩展模块未定义任何常量。

范例

Example#1 正则表达式例子

<?php
// 如果在 $string 中任何地方找到 "abc" 则返回 &true;
ereg ("abc", $string);

// 如果 $string 以 "abc" 开头则返回 &true;
ereg ("^abc", $string);

// 如果 $string 以 "abc" 结尾则返回 &true;
ereg ("abc$", $string);

// 如果用户浏览器是 Netscape 2,3 或 MSIE 3 则返回 &true;
eregi ("(ozilla.[23]|MSIE.3)", $HTTP_USER_AGENT);

// 将三个空格分隔的单词放入 $regs[1],$regs[2] 和 $regs[3] 中
ereg ("([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)", $string,$regs);

// 将 <br /> 标记放到 $string 开头
$string = ereg_replace ("^", "<br />", $string);

// 将 <br /> 标记放到 $string 结尾
$string = ereg_replace ("$", "<br />", $string);

// 删除 $string 中的所有换行符
$string = ereg_replace ("\n", "", $string);
?>

参见
Perl 兼容语法的正则表达式见 PCRE 函数。简单的命令行解释器风格的通配符匹配由 fnmatch() 提供。

Table of Contents
ereg_replace — 正则表达式替换
ereg — 正则表达式匹配
eregi_replace — 不区分大小写的正则表达式替换
eregi — 不区分大小写的正则表达式匹配
split — 用正则表达式将字符串分割到数组中
spliti — 用正则表达式不区分大小写将字符串分割到数组中
sql_regcase — 产生用于不区分大小的匹配的正则表达式