[分享]php pcre正则表达式完全教程--pcre官方文档翻译

goosman 2011-03-30 07:42:21
加精
翻译有不正确的地方, 恳请指正......本翻译过段时间录入php官方文档
translator: slefimpr
blog: http://blog.csdn.net/lgg201
mail: lgg860911@yahoo.com.cn


PCRE

简介

PCRE 扩展的正则表达式会有一个每个线程都可用的全局缓存用来缓存编译后的正则表达式.
PCRE在php4.2.0中是默认启用的, 可以通过—without-pcre-regex禁用. 在php 5.3.0之后, 这个扩展不能被禁用. 但是仍然可以使用—with-pcre-regex=DIR来实用一个外部的pcre库进行编译
配置

pcre.backtrack_limit: 默认100000, pcre回溯限制
pcre.recursion_limit: 默认100000, pcre的递归限制. 需要注意的是, 如果将这个值设置为一个很大的数字, 你可能会消耗掉所有的进程可用堆栈, 并且最终导致php崩溃(直到到达系统限制的堆栈大小)

预定义常量

PREG_PATTERN_ORDER

结果按照”规则”排序, 仅用于preg_match_all, 即$matches[0]是完整规则的匹配结果, $matches[1]是第一个子组匹配的结果
PREG_SET_ORDER:

结果按照”集合”排序, 仅用于preg_match_all, 即$matches[0]保存第一次匹配结果的所有结果(包含子组)信息, $matches[1]保存第二次的结果信息
PREG_OFFSET_CAPTURE

在捕获的结果中, 不仅包含结果子串, 还会包含子串在原字符串中的位置.
PREG_SPLIT_NO_EMPTY

告知preg_split仅返回非空的部分
PREG_SPLIT_DELIM_CAPTURE

告知preg_split同时捕获规则中的括号表达式匹配到的内容
PREG_SPLIT_OFFSET_CAPTURE

如果设置了这个标记, 每次匹配得到的结果的offset位置将会被同时返回.
PREG_NO_ERROR

如果preg_last_error调用后返回此值, 则表明正则没有错误
PREG_INTERNAL_ERROR

如果preg_last_error调用后返回此值, 则表明发生了PCRE内部错误
PREG_BACKTRACK_LIMIT_ERROR

如果回溯次数超过预设的值, preg_last_error函数返回此值
PREG_RECURSION_LIMIT_ERROR

如果递归次数超过预设的值, preg_last_error函数返回此值
PREG_BAD_UTF8_ERROR

如果preg的最后错误是由于异常的utf-8数据(仅在运行在utf-8模式正则表达式情况下)导致的, 那么preg_last_error返回此值


PREG_BAD_UTF8_OFFSET_ERROR

如果偏移量与合法的utf-8代码(仅在运行在utf-8模式正则表达式情况下)的开始点不匹配, preg_last_error的调用返回此值
PCRE_VERSION

返回pcre版本号和发布日期.

模式修饰符

i PCRE_CLASSES
大小写不敏感的修饰符
m PCRE_MULTILINE
多行匹配, 默认情况下, PCRE认为目标字符串是一组单行字符组成的(然而实际上它可能会包含多行). 元字符^仅匹配字符串的开始位置, 而元字符$则仅匹配字符串的末尾, 或者新行之前(除非设置了D修饰符). 这个修饰符和perl中工作一直, 使用后, ^和$会匹配每一行的开始和结尾
如果目标字符串中没有\n字符或者模式中没有出现^和$, 则设置此修饰符是没有任何影响的.
s PCRE_DOTALL
用来增强字符类.(点号)的功能, 默认情况下, 点号匹配任意字符, 但不包括换行符及以后内容. 使用此修饰符后, 可以匹配任意字符包括换行符
x PCRE_EXTENDED
如果设置了这个修饰符, 模式中的空白字符, 除非被转义或者在一个字符类中, 否则都被忽略. 在一个未转义的#之后直到下一个换行符之间的内容都会被正则表达式引擎忽略以方便添加注释.
e PREG_REPLACE_EVAL
使用此修饰符后, preg_replace的$replacement参数除了可以使用正常的反向引用来取得匹配值, 还可以在其中书写eval语法允许的字符串进行求值, 并将返回结果用于最终的替换.
A PCRE_ANCHORED
如果设置了此修饰符, 模式被强制成为”anchored”(锚点), 也就是说约束使其始终从字符串的嘴前面开始搜索. 这个影响也可以通过构造适当的规则来实现(perl中只能这样实现)
D PCRE_DOLLAR_ENDONLY
如果设置了这个修饰符, $会匹配目标字符串的结尾之前, 而如果没有设置这个修饰符, 如果目标字符串最后一个字符时换行符, $就会匹配该换行符之前而不是字符串结尾之前.
如果设置了m修饰符, 则这个修饰符会被忽略. 这一点和perl不一致
S
当一个模式需要多次使用的时候, 我们为了获得更高的匹配效率, 值得花费一些时间对其进行分析. 如果设置了这个修饰符, 将会进行这个额外的分析. 当前, 这种对一个模式的分析仅仅适用于非锚点的匹配(即没有一个单一固定的开始字符)
U PCRE_UNGREEDY
这个修饰符逆转了贪婪的模式, 如果没有这个设置, 默认情况下的正则匹配时贪婪的, 量词后增加了?的模式是非贪婪的, 但是如果设置了这个修饰符, 则刚好相反.
这个规则与perl是不兼容的.
也可以在模式中使用?U来达到同样的效果
X PCRE_EXTRA
这个修饰符启用了一个PCRE中与perl不兼容的额外功能. 任意反斜线后面跟一个没有特殊含义的字符会导致一个错误, 以此来保留这些组合以备后期扩展.
默认情况下, 和perl一样, 反斜线后跟一个没有特殊含义的字符会以该字符原意解释.
当前没有任何其他特性受此修饰符控制
J PCRE_INFO_JCHANGED
与内部选项?J相同, 用来改变本地PCRE_DUPNAMES选项. 允许子组有重复的名字
u PCRE8
这个修饰符打开一个PCRE中与perl不兼容的额外功能. 模式字符串被认为是UTF-8的.

与perl的不同之处

默认情况下,使用C库函数isspace()判定一个任意字符是否是空白字符, 尽管可以实用字符类表替代编译PCRE. 通常isspace()匹配空格, 换页, 换行, 回车, 水平制表符和垂直制表符. perl5不再将垂直制表符包括到空白字符集中. \v这个转移实际上在很长时间都没有得到perl文档的承认. 然而, 这个字符自身被认为是一个空白字符至少是在5.002之上. 在5.004和5.005它不和\s匹配.
PCRE 不允许前瞻断言的量词修饰, perl允许这样做, 但是这并不是你想象的那样.例如, (?!a){3}并不意味着断言接下来三个字符不是a, 而是断言下一个字符不是a并进行3次.
子模式的捕获发生在负向前瞻内部时会被计算, 但是在偏移向量中病没有设置它们的条目. perl从断言失败之前匹配得到的这些模式匹配结果中设置了它的数值变量 (因此是成功的), 但这也仅在负向前瞻断言只有一个分支的时候.
尽管目标字符串中支持二进制0字符, 但是他们在模式字符串中是不允许的, 因为他们是通过普通的C字符串传递的, 而C字符串以0字符结束. 转义序列”\x00”可以在模式中用于表示二进制0字符.
不支持下面的perl转义序列: \I, \u, \L, \U. 实际上这些都是通过perl一般的字符串处理来实现的, 而不是模式匹配引擎的一部分.
不支持perl的\G断言, 因为它与单模式匹配没有关系.
很显然, pcre不支持(?{代码})和(??{代码})的构造. 然而, 它支持递归模式
在perl 5.005_02中当设置为捕获字符串的模式中有部分重复的时候会有一些古怪的现象发生, 比如: /^(a(b)?)+$/捕获aba的时候, $2会被设置为b, 然而, 如果把模式修改为/^(aa(bb)?)+$/的时候, 用aabbaa去匹配, $2将不会得到匹配结果. 如果将模式修改为/^(aa(b(b))?)+$/的时候, $2和$3又都能够匹配到结果. 在perl 5.004中$2在这几种情况下都能够得到匹配结果, 并且PCRE中夜市这样. 如果未来perl修改为一致的那就不同了, PCRE可能接下来会修改.
还有一个没有解决的差异是perl 5.005_02中, 模式/^(a)?(?(1)a|b)+$/会匹配字符串”a”, 而pcre中不会. 然而, perl和pcre中/^(a)?a/匹配”a”都会得到相同的结果, $1都未被设置.
PCRE提供了一些对perl正则表达式的扩展
1. 虽然后瞻断言要求必须匹配固定长度的字符串, 然而后瞻断言的每个可选分支还是可以实用不同长度的字符串的, 而perl 5.005中要求它们必须拥有同样的长度
2. 如果PCRE_DOLLAR_ENDONLY设置了并且PCRE_MULTILINE没有设置, $元字符仅匹配字符末尾之前
3. 如果PCRE_EXTRA设置了, 反斜线紧跟一个没有特殊含义的字符将会导致错误
4. 如果PCRE_UNGREEDY设置了, 贪婪模式控制被逆转, 即: 默认是非贪婪模式, 在量词后增加?表明是贪婪模式.

与POSIX正则的区别

PCRE函数需要的模式以分隔符闭合的包含.
不像POSIX, PCRE扩展没有专门的函数用来区分大小写敏感. 取而代之的是使用i这个模式修饰符来达到相同的效果. 其他模式修饰符也可以用来改变匹配策略.
POSIX函数从最左面寻找最长的匹配, 但是PCRE在查找到第一个合法匹配后就结束. 如果字符串没有匹配到结果, 那么两者是没有差别的, 但是如果匹配到结果, 两者就会在结果和速度上都有差别. 为了说明这个不同之处, 考虑Jeffrey Friedl著的”精通正则表达式”一书中的例子. 使用one(self)?(selfsufficient)?这个模式来匹配oneselfsufficient这个字符串, PCRE将会产生oneself这个结果, 但是POSIX将会匹配到完整的字符串oneselfsufficient. 两者都从原始字符串中匹配到了结果, 但是POSIX需要的是最长的结果.

函数列表

mixed preg_replace(mixed $pattern, mixed $replacement, mixed $subject[, int $limit = -1[, int &$count]])

执行一个正则表达式的搜索和替换. 从$subject中搜索与$pattern匹配的结果并使用$replacement替换它们.
$pattern
要搜索的模式. 可以是字符串或者一个字符串数组.
e修饰符可以使preg_replace()函数在进行了参数替换(后向引用)后$replacement参数被当做php代码来执行. 请确保$replacement是合法的php代码, 否则会在包含preg_replace()的行上引发一个解析错误
$replacement
用于替换的字符串或字符串数组. 如果这个参数是字符串, 并且$pattern参数是一个数组, 所有的模式都是用这个字符串描述的规则进行替换. 如果$pattern和$replacement都是数组, 每个模式是用$replacement中对应的字符串进行替换. 如果$replacement中的元素比$pattern中的元素少, 那么$pattern中多出来的模式是用空字符串进行替换.
$replacement可以使用\\n或$n进行后向引用, 后者是首选的语法. 每个这样的后向引用语法会被替换为模式捕获到的第n个子组的匹配结果文本. n可以是0-99之间的数字. \\0或者$0后向引用的是整个模式匹配到的结果文本. 捕获子组的序列(这里的n)指的是代表子组的圆括号中的左括号在模式中出现的顺序(即第一个左括号代表的子组n=1, 第二个n=2, 依此类推), 如果想要在$replacement中使用反斜线, 需要对其进行转义(即PHP字符串”\\\\”)
当$replacement规则使用后向引用工作时, 并且后向引用后面需要立即使用一个数值, 比如”\\11”这个时候, 正则表达式引擎是没有办法判定你后向引用的子组是”\\1”而不是”\\11”, 这种情况下使用语法\${1}1来解决, 用{}将后向引用子组序号1和原文字符串1进行隔离.
当使用e修饰符时, 这个函数转义字符串中的一些字符(即: ’, “, \和空字符), 替换后向引用, 这些完成之后, 确保后向引用替换没有导致语法错误, 然后会将$replacement作为php代码执行, 并将执行结果作为最终用来替换的字符串.
$subject
用于搜索和替换的源字符串或字符串数组.
如果$subject是一个数组, 会搜索和替换每一个$subject中的元素, 并且同样返回一个数组
$limit
每个模式在每个$subject字符串中最大可以被替换的次数. 默认-1(不限制)
$count
一个引用方式的参数, 如果指定, 该参数最终被填充为进行替换的次数.
返回
如果$subject是一个数组, 返回数组, 否则返回字符串.
如果找到匹配, 返回替换后新的$subject. 其他情况下$subject会无变化返回. 当发生错误时返回NULL.
mixed preg_filter(mixed $pattern, mixed $replacement, mixed $subject[, int $limit = -1[, int &$count]])

这个函数等同于preg_replace, 除了它仅仅返回匹配结果. 更多关于此函数如何工作的信息, 请查看preg_replace文档
如果$subject参数是一个数组, 返回一个数组描述的匹配结果, 否则返回string
如果没有匹配到任何结果或发生了错误, 在$subject是数组时返回空数组, 否则返回NULL
array preg_grep(string $pattern, array $input[, int $flags = 0])

对$input中的每一个元素使用$pattern进行测试, 返回匹配的元素组成的数组. 如果$flags的值为PREG_GREP_INVERT, 那么将会返回不匹配的元素组成的数组. 返回的数组中元素的索引会被保留.
int preg_last_error(void)

返回最后一次pcre正则表达式执行的错误代码.
PREG_NO_ERROR/PREG_INTERNAL_ERROR/PREG_BACKTRACK_LIMIT_ERROR/PREG_RECURSION_LIMIT_ERROR/PREG_BAD_UTF8_ERROR/PREG_BAD_UTF8_OFFSET_ERROR等错误代码的意义详见pcre预定义常量部分.
int preg_match_all(string $pattern, string $subject, array &$matches[, int $flags[, int $offset]])

从$subject中搜索所有与$pattern给定正则表达式匹配的结果, 并且将匹配到的结果按照$flags指定的顺序放入$matches
在第一个匹配发现后, 子序列继续搜索直到最后一个匹配.
$pattern
用于搜索的模式
$subject
输入字符串
$matches
保存匹配结果的多维数组, 顺序依赖于$flags参数
$flags
可以是以下值的组合.(注意, 这并不是说PREG_PATTERN_ORDER和PREG_SET_ORDER可以同时使用)
如果没有给定任何flag, 默认启用的是PREG_PATTERN_ORDER
译注: 一个模式可能在字符串中发现多个匹配, 一个模式也会有多个子组, 这里的排序flag用来指明第一维表示子组还是多次匹配
PREG_PATTERN_ORDER: $matches[0]中包含第一个子组中所有匹配到的结果, $matches[1]中包含第二个子组中所有匹配到的结果.
PREG_SET_ORDER: $matches[0]中包含第一次匹配得到的结果(包含所有子组), $matches[1]包含第二次匹配得到的结果(包含所有子组)
PREG_OFFSET_CAPTURE: 如果传递了这个flag, 每一个匹配的字符串在返回时都会包含它在原始字符串中的偏移量. 注意: 这会改变$matches中最终输出的匹配结果数组元素, 原来是二维数组, 且第二维值是匹配到的字符串, 使用此flag后, 第二维会成为一个数值索引的数组, 其中第一个元素是匹配得到的字符串, 第二个元素是该匹配结果在原始字符串($subject)中的偏移量
$offset
模式$pattern从字符串($subject)的什么位置开始搜索. 这个可选参数用来控制从指定位置开始搜索(单位是字节)
注意: 实用$offset参数和传递实用substr($subject, $offset)截取后的$subject到preg_match_all()函数中是不一样的, 因为使用了$offset之后, $pattern依然可以使用^, $元字符进行首尾判断, 并且可以使用(?<=xx)进行前瞻断言.
返回
返回完成模式成功匹配的次数(可能是0), 当发生错误时返回FALSE
changelog
php5.2.2中, $pattern开始可以使用(?<name>), (?’name’)以及(?P<name>)来进行子组命名, 之前的版本中只接受(?P<name>)语法.
int preg_match(string $pattern, string $subject[, array &$matches[, int $flags[, int $offset]]])

使用$pattern搜索$subject的一个匹配, 如果给定了$matches参数, 则该参数用来保存搜索结果.
除了$flags参数不能接受PCRE_PATTERN_ORDER和PCRE_SET_ORDER来决定顺序外, 其余参数用法和preg_match_all()一致
返回$pattern匹配的次数. 它可能是0次(没有匹配)或者1次(因为preg_match()在搜索到一个匹配之后就会停止)
当发生错误的时候, 返回false.
注意: 如果你仅仅想判断一个字符串是否包含在另外一个字符串中, 不要使用preg_match, 请使用strpos或strstr
string preg_quote(string $str[, string $delimiter = null])

对$str中的每一个正则表达式语法定义的特殊字符进行转义. 这通常用于你有一个运行时字符串需要用作正则表达式进行匹配而它又包含特殊的正则表达式字符的时候.
特殊的正则表达式字符包括: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
可选的$delimiter参数用来指定额外的需要进行转义的字符, 这通常用于对你的正则表达式分隔符进行转义, 比如通常用作正则表达式分隔符的/
mixed preg_replace_callback(mixed $pattern, callback $callback, mixed $subject[, int $limit = -1[, int &$count]])

这个函数和preg_replace()的功能相同, 不同点在于$replacement使用了一个回调函数进行自定义的构造, 每一个获取到的对$pattern的完整匹配会对应一次替换, 也就是对$callback的调用, 调用时$callback接受到的参数是所有的子组, 其中第一个参数是第0个子组, 也就是对$pattern的完整匹配. 最终用作替换的字符串是$callback的返回值.
其他参数与preg_replace相同.
array preg_split(string $pattern, string $subject[, int $limit = -1[, int $flags = 0]])

用给定的$pattern分隔字符串形成数组返回.
$limit
用来限制最终返回的数组的最大长度, 默认-1表示不限制, 0也表示不限制.
$flags
可以是以下值的组合
PREG_SPLIT_NO_EMPTY: 如果此项被设置, 最终返回的数组仅包括分隔之后非空的部分
PREG_SPLIT_DELIM_CAPTURE: 如果此项设置, 在$pattern中的括号表达式奖会被捕获并作为返回
PREG_SPLIT_OFFSET_CAPTURE: 如果此项设置, 得到的分隔结果中不仅包含分隔后的字符串, 还会包括该子串在原始字符串中的偏移量. (译注: 假设使用”/ab/”分隔字符串”helloabworld”原来返回array(“hello”, “world”)), 那么使用此标记后返回array(array(“hello”, 0), array(“world”, 7))
注意: 如非必须, 不要使用preg_split, 你可以使用explode()或str_split()替代.
pcre/posix函数总结

ereg_replace, eregi_replace, preg_replace, preg_replace_callback, preg_filter用来做正则替换
ereg, eregi, preg_match, preg_match_all用来做正则匹配
split, spliti, preg_split用来做正则分割
preg_grep用来做正则查找.
...全文
7400 142 打赏 收藏 转发到动态 举报
写回复
用AI写文章
142 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnip591 2011-10-19
  • 打赏
  • 举报
回复
感谢分享,楼主辛苦了
  • 打赏
  • 举报
回复
学习...
limingchenxing 2011-07-18
  • 打赏
  • 举报
回复
不错,学习
夏之冰雪 2011-07-18
  • 打赏
  • 举报
回复
php的正则表达式啊,的确很强大的。
peterlew 2011-07-06
  • 打赏
  • 举报
回复
学习!顶!顶!
goosman 2011-07-06
  • 打赏
  • 举报
回复
LKK 2011-05-09
  • 打赏
  • 举报
回复
楼主辛苦了。。
_左岸阳光_ 2011-05-06
  • 打赏
  • 举报
回复
谢谢喽
liuzhengxi2010 2011-04-30
  • 打赏
  • 举报
回复
很好很不错,谢谢分享
爱科亚儿 2011-04-28
  • 打赏
  • 举报
回复
正则表达式在PHP语言中的作用与编程方法是怎么样的呢?
goosman 2011-04-28
  • 打赏
  • 举报
回复
[Quote=引用 130 楼 dwow_yujin 的回复:]

果国,自愧不如啊,赞!
[/Quote]

额....这里还能碰到熟人啊....哈哈..
jouvies 2011-04-28
  • 打赏
  • 举报
回复
感谢大大的分享!学习!爱死论坛了!
Dwow_yujin 2011-04-27
  • 打赏
  • 举报
回复
果国,自愧不如啊,赞!
muyijin 2011-04-23
  • 打赏
  • 举报
回复
好东西要收藏。
q594457287 2011-04-23
  • 打赏
  • 举报
回复
出售QQ信封]遗言者[QQ信封出售]QQ594457287

、⑩位打包;20 RMB→1000【号】 上线率达 % 9 0 至 % 9 5、

、⑨位打包;40 RMB→1000【号】 上线率达 % 9 0 至 % 9 5、

、⑧位打包;80 RMB→1000【号】 上线率达 % 9 0 至 % 9 5、

、⑦位打包;100 RMB→100【号】 上线率达 % 9 0 至 % 9 5、

、⑥位打包;4、RMB→1【号】 上线率达 % 9 0 至 % 9 5、

、⑤位打包;6、RMB→1【号】 上线率达 % 9 0 至 % 9 5、

↓二手QQ信封↓遗言者 QQ;594457287

、混合二手当天Q信 80 RMB→10000【号】 5千拿起、上线率达 % 8 0 至 % 9 0、

、混合二手隔夜Q信 60 RMB→10000【号】 5千拿起、上线率达 % 7 0 至 % 8 0、


1、不要怀疑我的信誉,

2、24小时/每天出信都是包装好的、纯⑥、纯⑦、纯⑧、纯⑨、纯⑩、全面有量!

3、信没有%100上线率、我们正常是%90以上、

4、不要问我,QB信、黄、黑、红、蓝砖、等信。告诉你‘没有’只有批量信!

5、不要问我,Q号有没有密保、我不可能给你一个个的查、

6、不要在我面前讨价还价,一分价钱一分货。质量说话。

7、没有不安全的号、只有不安全的人,我不是钱、做不到人人都喜欢。

8、网上无聊的人很多,请不要浪费我的时间。哥不是神人。不会指定盗号!

9、由于很多人被骗,第一次交易可以少量进。做到信誉满足客户!

10、我们有24/小时工作室、专人看守,名流远洋、大家放心。


遺言者QQ;594457287 交易支持;『支付宝、财付通』

交易规则、付款发货、决不重复、最后在说一次;决不重复、

(注)出信从来不走《链接》不走《担保交易》直接打款、谢谢合作! 遗言者 QQ;594457287


xiangdongdong1987 2011-04-22
  • 打赏
  • 举报
回复
崩溃!这个怎么能记得住呢!
dongge_001 2011-04-22
  • 打赏
  • 举报
回复
不错噢...
Sanana 2011-04-20
  • 打赏
  • 举报
回复
好家伙,头都看晕了!
yangkaixianglove 2011-04-19
  • 打赏
  • 举报
回复
应该没错的,我认为
hyryer 2011-04-15
  • 打赏
  • 举报
回复
正则,心中的痛苦啊...
加载更多回复(69)

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧