1
基础
正则表达式中大部分字符都是直接量字符,这意味着它们只匹配自身。
正则表达式默认区分大小写
正则表达式的真正强大来自于它们可以指定抽象模式来匹配许多不同的字符序列。
在正则表达式中可以指定3种基本的抽象模式:
· 在字符串中可以出现的字符集(例如,字母、数字和特殊的标点符号)
· 可选择性的集合(例如,
"com"、
"edu"、
"net"或
"org")
· 在字符串中重复的序列(例如,至少一个但是不多于5个的数字字符)
这3种模式可以按无数种方法结合在一起来创建正则表达式,以匹配像有效电话号码和URL之类的内容。
1.1
字符类
模式中方括号内的部分称为“字符类”。字符类中可用的元字符为:
/ 通用转义字符
^ 排除字符类,但仅当其为第一个字符时有效
- 指出字符范围
1.2
选择性
可以使用竖线(|)字符在正则表达式中指定可供选择的部分,表示正则表达式的"或"操作;
1.3
重复序列
要指定一个重复模式,要使用量词(quantifier)。量词在重复模式后面,用来说明要重复这个模式多少次。表4-6显示了POSIX 和 Perl正则表达式都支持的量词
表4-6:正则表达式量词
量 词
|
意 义
|
?
|
0或1
|
*
|
0或更多
|
+
|
1或更多
|
续表4-6:正则表达式量词
量 词
|
意 义
|
{n}
|
n次
|
{n,m}
|
至少n次,不超过m次
|
{n,}
|
至少n次
|
要重复单个字符,只要简单地把量词放在字符后面
1.4
子模式
以使用小括号把几个正则表达式组合在一起作为一个单独的单元来对待,这个单元被称为子模式(subpattern).
2 POSIX风格正则表达式
2.1
字符类
如表4-7所示,POSIX定义了许多可以在字符类中使用的命名字符集。在表4-7中给出的扩展是英语的。实际的字母根据使用者地区(locale)不同而不同。 译注1
表4-7:POSIX字符集
类
|
描 述
|
扩 展
|
[:alnum:]
|
字母和数字字符
|
[0-9a-zA-Z]
|
[:alpha:]
|
(letters)字母字符(字母)
|
[a-zA-Z]
|
[:ascii:]
|
7位ASCII
|
[/x01-/x7F]
|
[:blank:]
|
水平空白符(空格、制表符)
|
[ /t]
|
[:cntrl:]
|
控制字符
|
[/x01-/x1F]
|
[:digit:]
|
数字
|
[0-9]
|
[:graph:]
|
用墨水打印的字符(非空格、非控制字符)
|
[^/x01-/x20]
|
[:lower:]
|
小写字母
|
[a-z]
|
[:print:]
|
可打印字符(图形类加空格和制表符)
|
[/t/x20-/xFF]
|
[:punct:]
|
任意标点符号,如句点(.)和分号(;)
|
[-!"#$%&'( )*+,./:;<=>?@[///]^_'{|}~]
|
[:space:]
|
空白(换行、回车、制表符、空格、垂直制表符)
|
[/n/r/t /x0B]
|
[:upper:]
|
大写字母
|
[A-Z]
|
[:xdigit:]
|
十六进制数字
|
[0-9a-fA-F]
|
每一个[:something:]
类都可被用于替代一个字符类中的字符。
#不能把一个字符类当作一个范围的终点使用
#一些地区把某些字符序列当作一个单独的字符来考虑——它们被称为排序序列(collating sequence)。在字符类中匹配这些多字符序列中的一个时,要把它用[. 和 .]括起来。
例如,如果你的地区有排序序列“字”,你可以使用下面的字符类来匹配s、t或字:
[st[.字.]]
2.2
锚
锚(anchor) 将匹配限制在字符串中特定位置(锚不匹配目标字符串中的实际字符)。表4-8列出了POSIX正则表达式支持的锚。
表4-8:POSIX锚
锚
|
匹 配
|
^
|
字符串开始
|
$
|
字符串末尾
|
[[:<:]]
|
单词开始
|
[[:>:]]
|
单词末尾
|
#单词边界指在一个空白符和一个标识符(字母数组或下划线)之间的那一点
#注意字符串的开头和结尾也可以作为单词边界。
2.3 函数
POSIX风格的正则表达式有三类函数:匹配、替换和拆分。
ereg_replace - 正则表达式替换
ereg - 正则表达式匹配
eregi_replace - 不区分大小写的正则表达式替换
eregi - 不区分大小写的正则表达式匹配
split - 用正则表达式将字符串分割到数组中
spliti - 用正则表达式不区分大小写将字符串分割到数组中
sql_regcase - 产生用于不区分大小的匹配的正则表达式
3 Perl兼容正则表达式(PCRE Perl-Compatible Regular Expressions)
3.1 分隔符
Perl
风格的正则表达式模仿Perl模式的语法,即每个模式都必须用一对分隔符括起来。习惯上使用左斜杠(/),例如,/pattern/
。不过,任意非数字字母的字符(除了反斜杠(/)
)都可用于分隔一个Perl风格的模式。
3.
2
匹配行为
句点(.) 匹配任意除换行符(/n)之外的字符。
美元符号($) 匹配字符串的末尾或在换行符之前以换行符结尾的字符串。
3.3 字符类
Perl
风格的正则表达式不仅支持POSIX字符类,而且定义了一些自己的字符类,如表4-9所示:
表4-7:POSIX字符集
类
|
描 述
|
扩 展
|
[:alnum:]
|
字母和数字字符
|
[0-9a-zA-Z]
|
[:alpha:]
|
(letters)字母字符(字母)
|
[a-zA-Z]
|
[:ascii:]
|
7位ASCII
|
[/x01-/x7F]
|
[:blank:]
|
水平空白符(空格、制表符)
|
[ /t]
|
[:cntrl:]
|
控制字符
|
[/x01-/x1F]
|
[:digit:]
|
数字
|
[0-9]
|
[:graph:]
|
用墨水打印的字符(非空格、非控制字符)
|
[^/x01-/x20]
|
[:lower:]
|
小写字母
|
[a-z]
|
[:print:]
|
可打印字符(图形类加空格和制表符)
|
[/t/x20-/xFF]
|
[:punct:]
|
任意标点符号,如句点(.)和分号(;)
|
[-!"#$%&'( )*+,./:;<=>?@[///]^_'{|}~]
|
[:space:]
|
空白(换行、回车、制表符、空格、垂直制表符)
|
[/n/r/t /x0B]
|
[:upper:]
|
大写字母
|
[A-Z]
|
[:xdigit:]
|
十六进制数字
|
[0-9a-fA-F]
|
表4-9 Perl风格的字符类
字符类
|
意 义
|
扩 展
|
/s
|
空白符
|
[/r/n /t]
|
/S
|
非空白符
|
[^/r/n /t]
|
/w
|
单词(标识符)字符
|
[0-9A-Za-z_]
|
/W
|
非单词(标识符)字符
|
[^0-9A-Za-z_]
|
/d
|
数字
|
[0-9]
|
/D
|
非数字
|
[^0-9]
|
3.4 锚
Perl
风格的正则表达式也支持附加锚(其自定义的锚标记),如表4-10所示:
表4-10:Perl风格的锚
断 言
|
意 义
|
/b
|
单词边界(在/w和/W之间或在字符串开头或末尾)
|
/B
|
非单词边界(在/w和/w或/W和/W之间)
|
/A
|
字符串开头
|
/Z
|
字符串末尾或在末尾的/n之前
|
/z
|
字符串末尾
|
续表4-10:Perl风格的锚
断 言
|
意 义
|
^
|
行的开头(或如果/m标志启用的话在/n之后)
|
$
|
行的末尾(或如果/m标志启用的话在/n之前)
|
3.5
量词和贪婪性
即当有一个量词时,引擎在仍然满足匹配模式的情况下尽可能多地进行匹配。
贪婪性会产生一个问题。有时你需要最少匹配(非贪婪匹配),就是说量词尽可能少的匹配满足模式的剩余部分。Perl提供了一组用于最小匹配的量词。它们很容易记住,因为它们和贪婪量词相同,只是附加了一个问号(?)。
表4-11:Perl兼容正则表达式中支持的贪婪量词和非贪婪量词
贪婪量词
|
非贪婪量词
|
?
|
??
|
*
|
*?
|
+
|
+?
|
{m}
|
{m}?
|
{m,}
|
{m,}?
|
{m,n}
|
{m,n}?
|
另外一个更快的方法是使用一个字符类来匹配每个非大于字符到下一个大于字符:
preg_match('/(<[^>]*>)/', 'do <b>not</b> press the button', $match);
// $match[1] 是 '<b>'
3.6
非捕获匹配
如果把模式的一部分用小括号括起来,那么匹配子模式的文本被捕获并且可以在后面访问。但是有时你想创建一个不捕获匹配文本的子模式,那么在
Perl
兼容正则表达式中可以使用(?:subpattern)
结构来这样做
preg_match('/(?:ello)(.*)/', 'hello biafra', $match); print_r($match);
Array ( [0] => ello biafra [1] => biafra )
而 preg_match('/(ello)(.*)/', 'hello biafra', $match); print_r($match);
结果是:
Array ( [0] => ello biafra [1] => ello [2] => biafra )
|
3.7
逆向引用
可以使用一个逆向引用(backreference)来引用模式中之前被捕获的字符串:
/1引用第一个子模式的内容,
/2引用第二个,依此类推。
如果嵌套了子模式,那么第一个引用以第一个左小括号开始,第二个引用以第二个左小括号开始,依此类推。
#不能捕获超过99个子模式。
3.8
后缀选项
Perl风格的正则表达式允许把单个字符选项(标志)放在正则表达式模式后面来修改匹配的解释或行为。例如,要进行不区分大小写的匹配,可以简单地使用i标志:
preg_match('/cat/i', 'Stop, Catherine!'); // returns true返回true
表4-12显示了在Perl兼容正则表达式中支持的来自Perl的修饰符:
表4-12:Perl标志
修饰符
|
意 义
|
/regexp/i
|
不区分大小写的匹配
|
/regexp/s
|
使句点(.)匹配任何字符,包括换行符(/n)
|
/regexp/x
|
从模式中删除空白符和注释
|
/regexp/m
|
使^匹配换行符 (/n)之后的内容,美元符号($)匹配换行符 (/n)之前的内容
|
/regexp/e
|
如果替换字符串是PHP代码,使用eval()执行该代码来得到实际的替换字符串。
|
PHP的Perl兼容正则表达式函数也支持在Perl中不支持的其他修饰符,如表4-13所示:
表4-13:其他的PHP标志
修饰符
|
意 义
|
/regexp/U
|
颠倒子模式的贪婪性;*和+尽可能少地匹配而不是尽可能多。
|
/regexp/u
|
把模式字符串当作UTF-8编码对待
|
/regexp/X
|
如果一个反斜杠之后跟着没有特殊意义的字符,将产生一个错误
|
/regexp/A
|
把锚定位在字符串的开头就像模式中有^一样
|
/regexp/D
|
使$字符仅匹配一行的末尾
|
/regexp/S
|
使表达式解析器更加小心地检查模式的结构,使得第二次运行时(如在一个循环中)加快速度
|
3.9
内联选项
除了在模式结束分隔符之后指定模式选项之外,还可以在一个模式内部指定仅运用于部分模式的选项。语法如下:
(?flags:subpattern)
# i、m、s、U、x和X
选项可被用在这种方式的内部。一次可以使用多个选项.
# 一个选项前如果有连字符(-)表示关闭此选项:
# 可以启用或禁用标志直到封闭的子模式或模式末尾
#内置标志不能用于捕获字符串,需要设置一个附加的小括号来完成捕获(如上示例中用小括号定义了一个子模式)。
3.10
前向和后向断言
有时在模式中能够指出”如果这里是下一个,就匹配这里”是很有用的。这在拆分字符串时是很常见的。这种正则表达式描述了分隔符,但不返回。可以使用前向断言(lookahead assertion)来确保在分隔符之后有更多的数据(因为没有匹配它,所以阻止被返回)。类似的,后向断言(lookbehind assertion)检查前面的文字。
前向和后向各有两种形式:正(positive)和负(negative)。正的前向或后向表示“下一个/前面的文本必须如此”。负的前向和后向表示“下一个/前面的文本必须不是这样”。表4-14展示了在Perl兼容模式中可以使用的4种结构。这4种结构都不捕获文本。
表4-14:前向和后向断言
结 构
|
意 义
|
(?=subpattern)
|
正前向
|
(?!subpattern)
|
负前向
|
(?<=subpattern)
|
正后向
|
(?<!subpattern)
|
负后向
|
这里唯一的技巧是,要得到一个后向的模式来查看最后一个字符是否是反斜杠,我们需要转义反斜杠来防止正则表达式引擎看到表示右小括号的"/)"。也就是说,我们要在反斜杠前面再加上一个反斜杠:"//)"。但是PHP中引用字符串的规则认为//将生成一个单独反斜杠,所以我们需要通过正则表达式用4个反斜杠来得到一个反斜杠。这就是为什么大家都说正则表达式难以阅读的原因。
Perl限制后向只能用于固定长度的表达式上,即表达式不能包含量词,并且如果使用选择符(|),所有的选择都必须是相同长度。Perl兼容的正则表达式引擎也禁止在后向中使用量词,但是允许不同长度的选择。
3.11 剪切
我们很少使用的一次性子模式(once-only subpattern)或称剪切(cut),可以防止正则表达式在对待某些类型的模式时出现最坏的情况。一旦匹配,正则表达式就不会回溯子模式。
剪切不会改变匹配的结果,只是让它尽快报错。
3.12 条件表达式
在正则表达式中条件表达式就像一个if语句。一般格式为:
(?(condition)yespattern)
(?(condition)yespattern|nopattern)
如果断言成立,正则表达式引擎匹配yespattern。对于第二个形式,如果断言不成立,正则表达式引擎跳过
yespattern并试图匹配nopattern。
断言可以是两种类型中的一种:逆向引用(backreference) 或前向和后向匹配(lookahead和lookbehind match)。要引用一个之前匹配的子字符串,要求断言是从1到99中的数字(大多数的逆向引用都可以)。只有逆向引用被匹配时,条件才能使用断言中的模式。如果断言不是逆向引用,那么它必须是正或负的前向或后向断言。
3.13 正则表达式相关函数
有5类函数可用于Perl兼容正则表达式:匹配、替换、拆分、过滤和引用文本的通用函数。
preg_grep - 返回与模式匹配的数组单元
preg_last_error - Returns the error code of the last PCRE regex execution
preg_match_all - 进行全局正则表达式匹配
preg_match - 进行正则表达式匹配
preg_quote - 转义正则表达式字符
preg_replace_callback - 用回调函数执行正则表达式的搜索和替换
preg_replace - 执行正则表达式的搜索和替换
preg_split - 用正则表达式分割字符串