翻译有不正确的地方, 恳请指正......本翻译过段时间录入php官方文档 translator: slefimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn PCRE 简介 PCRE 扩展的正则表达式会有一个每个线程都可用的全局缓存用来缓存编译后的正则表达式 .
翻译有不正确的地方, 恳请指正......本翻译过段时间录入php官方文档
translator: slefimpr
blog: http://blog.csdn.net/lgg201
mail: lgg860911@yahoo.com.cn
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_match_all, 即$matches[0]是完整规则的匹配结果, $matches[1]是第一个子组匹配的结果
结果按照”集合”排序, 仅用于preg_match_all, 即$matches[0]保存第一次匹配结果的所有结果(包含子组)信息, $matches[1]保存第二次的结果信息
在捕获的结果中, 不仅包含结果子串, 还会包含子串在原字符串中的位置.
告知preg_split仅返回非空的部分
告知preg_split同时捕获规则中的括号表达式匹配到的内容
如果设置了这个标记, 每次匹配得到的结果的offset位置将会被同时返回.
如果preg_last_error调用后返回此值, 则表明正则没有错误
如果preg_last_error调用后返回此值, 则表明发生了PCRE内部错误
如果回溯次数超过预设的值, preg_last_error函数返回此值
如果递归次数超过预设的值, preg_last_error函数返回此值
如果preg的最后错误是由于异常的utf-8数据(仅在运行在utf-8模式正则表达式情况下)导致的, 那么preg_last_error返回此值
如果偏移量与合法的utf-8代码(仅在运行在utf-8模式正则表达式情况下)的开始点不匹配, preg_last_error的调用返回此值
返回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的.
默认情况下,使用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设置了, 贪婪模式控制被逆转, 即: 默认是非贪婪模式, 在量词后增加?表明是贪婪模式.
PCRE函数需要的模式以分隔符闭合的包含.
不像POSIX, PCRE扩展没有专门的函数用来区分大小写敏感. 取而代之的是使用i这个模式修饰符来达到相同的效果. 其他模式修饰符也可以用来改变匹配策略.
POSIX函数从最左面寻找最长的匹配, 但是PCRE在查找到第一个合法匹配后就结束. 如果字符串没有匹配到结果, 那么两者是没有差别的, 但是如果匹配到结果, 两者就会在结果和速度上都有差别. 为了说明这个不同之处, 考虑Jeffrey Friedl著的”精通正则表达式”一书中的例子. 使用one(self)?(selfsufficient)?这个模式来匹配oneselfsufficient这个字符串, PCRE将会产生oneself这个结果, 但是POSIX将会匹配到完整的字符串oneselfsufficient. 两者都从原始字符串中匹配到了结果, 但是POSIX需要的是最长的结果.
执行一个正则表达式的搜索和替换. 从$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.
这个函数等同于preg_replace, 除了它仅仅返回匹配结果. 更多关于此函数如何工作的信息, 请查看preg_replace文档
如果$subject参数是一个数组, 返回一个数组描述的匹配结果, 否则返回string
如果没有匹配到任何结果或发生了错误, 在$subject是数组时返回空数组, 否则返回NULL
对$input中的每一个元素使用$pattern进行测试, 返回匹配的元素组成的数组. 如果$flags的值为PREG_GREP_INVERT, 那么将会返回不匹配的元素组成的数组. 返回的数组中元素的索引会被保留.
返回最后一次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预定义常量部分.
从$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依然可以使用^, $元字符进行首尾判断, 并且可以使用(?进行前瞻断言.
返回
返回完成模式成功匹配的次数(可能是0), 当发生错误时返回FALSE
changelog
php5.2.2中, $pattern开始可以使用(?
使用$pattern搜索$subject的一个匹配, 如果给定了$matches参数, 则该参数用来保存搜索结果.
除了$flags参数不能接受PCRE_PATTERN_ORDER和PCRE_SET_ORDER来决定顺序外, 其余参数用法和preg_match_all()一致
返回$pattern匹配的次数. 它可能是0次(没有匹配)或者1次(因为preg_match()在搜索到一个匹配之后就会停止)
当发生错误的时候, 返回false.
注意: 如果你仅仅想判断一个字符串是否包含在另外一个字符串中, 不要使用preg_match, 请使用strpos或strstr
对$str中的每一个正则表达式语法定义的特殊字符进行转义. 这通常用于你有一个运行时字符串需要用作正则表达式进行匹配而它又包含特殊的正则表达式字符的时候.
特殊的正则表达式字符包括: . / + * ? [ ^ ] $ ( ) { } = ! | : -
可选的$delimiter参数用来指定额外的需要进行转义的字符, 这通常用于对你的正则表达式分隔符进行转义, 比如通常用作正则表达式分隔符的/
这个函数和preg_replace()的功能相同, 不同点在于$replacement使用了一个回调函数进行自定义的构造, 每一个获取到的对$pattern的完整匹配会对应一次替换, 也就是对$callback的调用, 调用时$callback接受到的参数是所有的子组, 其中第一个参数是第0个子组, 也就是对$pattern的完整匹配. 最终用作替换的字符串是$callback的返回值.
其他参数与preg_replace相同.
用给定的$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()替代.
ereg_replace, eregi_replace, preg_replace, preg_replace_callback, preg_filter用来做正则替换
ereg, eregi, preg_match, preg_match_all用来做正则匹配
split, spliti, preg_split用来做正则分割
preg_grep用来做正则查找.
下面描述的是PCRE支持的正则表达式语法和语义. 正则表达式同样在perl文档或其他一些书籍中有所描述, 其中有非常丰富的示例. Jeffrey Friedl的”精通正则表达式”一书非常详细的讨论了这些内容. 这里的描述目的仅作为参考手册.
一个正则表达式的模式从左至右不断匹配一个目标字符串. 大多数字符自身就代表一个模式, 并且匹配目标字符串中对应的字符. 作为一个简单的例子The quick brown fox匹配在目标字符串中与其相同的部分.
当使用PCRE函数的时候, 它要求模式使用闭合的分隔符包裹. 分隔符可以是任意的非字母数字, 非反斜线, 非空的字符.
经常用作分隔符的符号有/, #, ~等.
如果在模式中需要使用分隔符自身, 就需要通过在前面追加一个反斜线对其进行转义. 如果分隔符经常需要在模式中出现, 那么一个好的选择就是选用另外的字符当做分隔符.
preg_quote函数可以用于转义字符串中被用作正则表达式特殊字符的字符, 并且它的第二个参数可以用于指定分隔符同样对其进行转义.
除了上面提到的分隔符, 还可以使用括号样式的分隔符, 左括号和右括号分别位于模式字符串的开始和结束位置即可(大括号{}, 中括号[],小括号()都可以)
你可以在结束的分隔符后面增加模式修饰符.
正则表达式的威力在于它在模式中拥有选择和重复的能力. 这些编码在模式中被称作元字符, 也就是说这些字符不再单纯代表它们自己, 而是赋予了特别的含义.
有两种不同的元字符, 一种是可以在方括号外任何地方使用的, 另外一种是在方括号内使用的.
/ 通常用于字符转义
^ 代表目标字符串的开始位置(在多行模式下为行首)
$ 代表目标字符串的末尾位置(在多行模式下为行尾)
. 除了换行符外的任意字符(这是默认情况, 其他意义参见模式修饰符s)
[ 字符类定义的开始标记
] 字符类定义的结束标记
| 开始一个可选分支
( 子组开始标记
) 子组结束标记
? 作为(数)量词(直接位于字符类/子组后面), 代表0个或1个. 位于量词后面, 逆转贪婪模式
* 0个或任意多个
+ 1个或任意多个
{ 自定义量词开始标记
} 自定义量词结束标记
/ 用于转义字符
^ 仅当作为中括号第一个字符时, 表明该字符类取反, 即匹配不在其中罗列的字符
- 声明字符范围
] 自定义字符类结束
反斜线有多种用法. 首先, 如果它后面紧跟一个非数字字母的字符, 表明取消任何该字符的特殊含义, 进行原文匹配. 这个将反斜线作为转义字符的应用在字符类内部和外部都有效.
比如, 如果你想要匹配”*”字符, 你需要在模式中使用”/*”. 这适用于一个字符在不进行转义会有特殊含义的情况下. 但是, 对于非数字字母的字符, 总是在需要其进行原文匹配的时候在它前面增加一个反斜线, 来声明它代表自己, 这是安全的. 如果要匹配一个反斜线, 那么在模式中使用”//”.
注意: 反斜线在单引号字符串和双引号字符串中都有特殊含义, 因此要匹配一个反斜线, 模式中必须写为”////”. 译注: “////”, 首先它作为字符串, 反斜线会进行转义, 那么转义后的结果是///, 这个才是正则表达式引擎拿到的模式, 而正则表达式引擎也认为/是转义标记, 它会将分隔符/进行转义, 从而得到的是一个错误, 因此, 需要4个反斜线才可以匹配一个反斜线.
如果一个模式被使用PCRE_EXTENDED选项编译, 模式中的空白字符(除了字符类中的)和未转义的#到行末的所有字符都会被忽略. 要在这种情况下使用空白字符或者#, 就需要对其进行转义.
反斜线的第二种用途提供了一种对非打印字符进行可见编码的控制手段. 除了二进制的0会终结一个模式外, 并不会严格的限制非打印字符(自身)的出现, 但是当一个模式以文本编辑器的方式编辑准备的时候, 使用下面的转义序列相比使用二进制字符会更加容易.
/a 响铃字符(十六进制 07)
/cx control-x, x是任意字符
/e 转义(十六进制1B)
/f 换页(十六进制 0C)
/n 换行(十六进制 0A)
/p{xx} 一个符合xx属性的字符, 详细查看unicode属性
/P{xx} 一个不符合xx属性的字符, 详细查看unicode属性
/r 回车(十六进制 0D)
/t 水平制表符(十六进制 09)
/xhh hh十六进制编码的字符, 详细查看unicode属性
/ddd ddd八进制编码的字符, 或者后向引用
“/cx”的确切效果如下: 如果”x”是一个小写字母, 它被转换为大写. 接着, 将字符的第6位(十六进制 40, 右数第一个位为第0位)取反. 比如”/cz”成为十六进制的1A, “/c{“成为十六进制3B, “/c;”成为十六进制7B.
在”/x”后面,读取两个十六进制数(字母可以是大写或小写). 在UTF-8模式, “/x{…}”允许使用, 花括号内的内容是十六进制有效数字. 它将给出的十六进制数字解释为UTF-8字符代码. 原来的十六进制转义序列, /xhh, 匹配一个双字节的UTF-8字符, 如果它的值大于127
在”/0”之后, 读取两个八进制数. 所有情况下, 如果数少于2个, 则直接使用. 序列”/0/x/07”指定了两个二进制0紧跟着一个BEL字符. 请确保初始的0之后的两个数字是合法的八进制数.
处理一个反斜线紧跟着的不是0的数字的情况比较复杂. 在字符类外部, PCRE读取它并以十进制读取紧随其后的数字. 如果数值小于10,或者之前捕获到了该数字能够代表的左括号(子组), 整个数字序列被认为是后向引用.后向引用如何工作在后面描述, 接下来就会讨论括号子组.
在一个字符类里面, 或者十进制数大于9并且没有那么多的子组被捕获, PCRE重新读取反斜线后的第三个8进制数字, 并且从最低的8位生成单字节值. 任何的后续数字都代表它们自身. 例如:
/040: 空格的另一种写法
/40:当提供了少于40个子组时, 也是空格
/7: 始终是后向引用
/11:可能是后向引用, 也可能是制表符
/011:始终是制表符
/0113:一个制表符紧跟一个3(因为每次最多只读取3个8进制