PHP正则式PCRE
PHP正则式PCRE的总结差不多就下边这些了。参考 PCRE与perl的差异 。
锚(^、$、\A、\Z/\z)
^、$ 在多行模式(PCRE_MULTILINE)下构造非紧固模式,在单行模式(美元符号可匹配字符串尾部的一个换行符)下可构造紧固模式;而\A、\Z / \z只用于构造紧固模式(\G表示在目标中首次匹配位置,还可以与$offset参数一起使用)。
断言
一个断言指定一个必须在特定位置匹配的条件,不会导致当前的匹配点发生改变,不会从目标字符串中消耗任何字符,因此也不会出现在结果中。一个断言子组以前瞻断言“(?=)”或“(?!)”、后瞻断言“(?<=)”或“(?<!)”形式出现:
(1)\b指单词边界(\b在字符类中表示退格backspace字符),\B指非单词边界。
(2)当字符串结束字符为换行符时,\Z 会将其看做字符串结尾匹配, 而 \z 只匹配字符串结尾。
(3)前瞻断言(?!foo)bar会查找到任意的barxxxxx而非foo跟随bar的情况。
(4)后瞻断言的内容被严格限制为只能用于匹配定长字符串,比如 (?<=bullock|donkey) 是允许的,但是 (?<!dogs?|cats?)、 (?<=ab(c|de)) 将会引发一个编译期的错误。
(5)多个断言(任意顺序)可以同时出现,如 (?<=\d{3})(?<!999)foo 匹配前面有三个数字但不是 ”999” 的字符串 ”foo”。
(6)断言可以以任意复杂度嵌套,比如 (?<=(?<!foo)bar)baz 匹配前面有 ”bar” 但是 ”bar” 前面没有 ”foo” 的 ”baz”, 另外(?<=\d{3}…(?<!999))foo 匹配前面有三个数字字符紧跟 3 个不是 999 的任意字符的 ”foo”。
(7)如果所有的断言都包含一个捕获子组,那么为了在整个模式中捕获子组计数的目的,它们都会被计算在内;然而子字符串的捕获仅可以用于正面断言,因为对于消极的断言是没有意义的。
内部选项(?)
如果一个选项在子组内部设置,仅仅改变子组中剩余的部分,因此 (a(?i)b)c 仅仅匹配 ”abc” 和 ”aBc” (假设没有使用 PCRE_CASELESS 选项);但在同一个子模式中, 一个分支的内部选项设置会穿透到后面的其他分支中去,比如 (a(?i)b|c) 匹配”ab”或“aB”或“c”或”C”(选项是在编译期确定下来的,在匹配 ”C” 时第一个分支已被丢弃)。(?im) 设置表明多行大小写不敏感匹配, 而(?im-sx) 设置了 PCRE_CASELESS,PCRE_MULTILINE, 但是同时取消了 PCRE_DOTALL 和 PCRE_EXTENDED。 如果一个字母即出现在 - 之前, 也出现在 - 之后,这个选项被取消设置。
模式修饰符
主要有i(PCRE_CASELESS)、m(PCRE_MULTILINE)、s(PCRE_DOTALL,但[.]只匹配单个.字符)、x(PCRE_EXTENDED)、A(PCRE_ANCHORED)、D(PCRE_DOLLAR_ENDONLY)、U(PCRE_UNGREEDY)等。模式修饰符中的空格、换行符会被忽略,其他字符会导致错误。
子组/子模式与分支(|)
子组通过圆括号(其作用是局部化和捕获子组,而“(?:)”不捕获子组,“(?|)”使可多个分支复用一个后向引用编号)来分隔界定,并且它们可以嵌套:
(1)cat(arcat|erpillar|)匹配 ”cat”, “cataract”, “caterpillar” 中的一个。
(2)一次性子组(非捕获子组)和后瞻断言结合使用来指定在目标字符串末尾的有效匹配,比如^(?>.*)(?<=abcd)相对于^.*abcd$更为高效。
(3)条件子组(非捕获子组)型如(?(condition)yes-pattern)、(?(condition)yes-pattern|no-pattern),condition是数字(后向引用某个捕捉子组)或字串或断言。
(\()?[^()]+(?(1)\))
改模式匹配一个没有括号的或者闭合括号包裹的字符序列。
(4)命名子组(捕获子组)形如 (?P<name>pattern)、(?<name>pattern)、(?’name’pattern),可通过(?P>name)、(?P&name)形式在模式中再次引用命名子组,但这种引用不可捕获。
重复/量词
* | 等价于 {0,} |
+ | 等价于 {1,} |
? | 等价于 {0,1} |
默认情况下,量词都是”贪婪”的,也就是说, 它们会在不导致模式匹配失败的前提下,尽可能多的匹配字符(直到最大允许的匹配次数),如对C代码“/* first comment*/ not comment /*second comment*/”匹配注释使用下列模式会匹配到整个字符串;
/\*.*\*/
然而,如果一个量词紧跟着一个 ?(?起到模式反转的作用,也就是说如果设置了 PCRE_UNGREEDY((?U),且对目标使用括号如((?U).+)),模式将反转为贪婪;而如果量词紧跟着一个+,表示任何情况下都使用贪婪模式,因此 .*?abc 匹配 ”aabc”, 但是 .*+abc 不匹配) 标记,它就会成为懒惰(非贪婪)模式, 只做尽可能少的匹配。 因此上述模式应该改成这样:
/\*.*?\*/
补充一下,在贪婪或懒惰模式下,都是在保证成功的条件下来控制匹配的重复次数最多(/.*a/取决于最后一个a所在的位置)或最少:
//$match = Array ( [0] => 214sfsbbb )
$patt = '/^\w*b$/';
preg_match($patt,'214sfsbbb',$match); //$match = Array ( [0] => 214sfsbbb )
$patt = '/^\w*?b$/';
preg_match($patt,'214sfsbbb',$match); //$match = Array ( [0] => 214sfsbbb )
$patt = '/^\w*b/';
preg_match($patt,'214sfsbbb',$match); //$match = Array ( [0] => 214sfsb )
$patt = '/^\w*?b/';
preg_match($patt,'214sfsbbb',$match); $subject = 'Aaaaaa Bbb';
$target = 0;
//$subject = "0123456 7B8b9b10"
$subject = preg_replace_callback_array(
[
'/a?/i' => function ($match) use (&$target) {
return $target++;
},
],
$subject
);
字符类与转义字符
字符类\d、\D、 \s(任意空白字符,包括\r、\n、\t)、\S(任意非空白字符)、\w(任意单词字符,包括字母、数字和_) 和 \W 也可以出现在一个字符类中, 用以将其匹配的字符类加入到新的自定义字符类中。比如, [\dABCDEF] 匹配任意合法的 16 进制数, [^\W_] 匹配任何字母或数字但不匹配下划线。\Q 和 \E 可忽略正则表达式元字符,
\w+\Q.$.\E$
该模式会匹配一个或多个单词字符,紧接着一个点号,一个$,一个点号, 最后锚向字符串末尾;\K 可以用于重置匹配,比如 foot\Kbar 匹配”footbar”,但是得到的匹配结果是 ”bar”。
注释
模式中形如“(?# comments)”的部分表示注释内容。如果设置了 PCRE_EXTENDED 选项, 一个字符类外部的未转义的 # 字符就代表本行剩余部分为注释。
递归模式(?R)
(?R) 提供了递归的这种特殊用法,如
\(((?>[^()]+)|(?R))*\)
该模式可匹配字串(ab(cd)ef)。
分隔符
分隔符可以使任意非字母数字、非反斜线、非空白字符,如正斜线(/)、hash符号(#)、取反符号(~)等。
后向引用
(?1)、(?2)、(?P>name)、(?P&name)、(?P=name)、\1、\k<name>、\k’name’、\k{name}、\g{name}等形式可以用于引用之前定义的捕获子组。需注意,\n复用捕获组匹配结果,而(?n)、(?P>name)、(?P&name)复用模式。(a|(bc))\2 总是在匹配 ”a” 开头而不是 ”bc” 开头的字符串时失败,故可以换成(a|(bc))(?2)。对后向引用后有数字可以空格分隔并使用x修饰符,或使用\g{n}这种格式(序列\1, \g1,\g{1}之间是同义关系),(foo)(bar)\g{-1} 可以匹配字符串 ”foobarbar”。子组内部后向引用自己(a\1)会失败,但(a|b\1)*遇到aba会成功;也就是模式在第一次迭代的时候,必须能够保证不需要匹配后向引用。
$data = 'a { b { 1 } c { d { 2 } } }';
preg_match('/a (?<R>\{(?:[^{}]+|(?&R))*\})/', $data, $m);
var_dump($m);
array(3) {
[0]=> string(27) "a { b { 1 } c { d { 2 } } }"
["R"]=> string(25) "{ b { 1 } c { d { 2 } } }"
[1]=> string(25) "{ b { 1 } c { d { 2 } } }"
}
PCRE不允许前瞻断言的量词修饰
(?!a){3}并不意味着接下来 3 个字符不是 a,而是断言下一个字符不是 a 并进行了 3 次断言。
//verify email address
//$match: Array ( [0] => w12aq.e_@124afasf.com [1] => 124afasf. )
$patt = '/^(?!_|-)(?>[\w.-]+)@(?!-)(?>((?>[a-zA-Z0-9-]+)\.)+)[a-zA-Z]{2,46}$/';
preg_match($patt,'w12aq.e_@124afasf.com',$match); //$match: Array ( [0] => Sunday [day] => Sunday [1] => Sunday )
$patt = '/(?<day>:(?i)saturday|sunday)/';
preg_match($patt,'Sunday',$match); //$match: Array ( [0] => Sunday [1] => Sun )
$patt = '/(?|(Sat)ur|(Sun))day/';
preg_match($patt,'Sunday',$match); //子组发生重复多次匹配时,捕获的是最新一次的值
//$match: Array ( [0] => (ab(cd)ef) [1] => ab(cd)ef [2] => ef )
$patt = '/\( ( ( (?>[^()]+) | (?R) )* ) \)/x';
preg_match($patt,'(ab(cd)ef)',$match); //命名子组可通过名称或序号来再次引用
//$match: Array ( [0] => 23ab45cd56 [number] => 23 [1] => 23 )
$patt = '/^(?P<number>\d+)ab(?P>number)cd(?1)$/';
preg_match($patt,'23ab45cd56',$match); //下列模式相当于^.*abcd$
//$match: Array ( [0] => 23abcd )
$patt = '/^(?>.*)(?<=abcd)/';
preg_match($patt,'23abcd',$match); //下列模式用于XML去空及压缩
$package = '<?xml version="1.0" encoding="UTF-8"?>
<PARAM>
<DBID>35</DBID>
<SEQUENCE>atgtca</SEQUENCE>
<MAXNS>10</MAXNS>
<MINIDENTITIES>90</MINIDENTITIES>
<MAXEVALUE>10</MAXEVALUE>
<USERNAME>ad m
in</USERNAME>
<PASSWORD>111111</PASSWORD>
<TYPE>P</TYPE>
<RETURN_TYPE></RETURN_TYPE>
</PARAM>';
// 去除空元素
$package = preg_replace('/<(\w+)[^>]*>\s*<\/\1>|<\w+[^>]*\/>/i', '', $package);
// XML压缩
$package = preg_replace('/(?<=>)\s+(?=<\/?\w+>)/i', '', $package);
PCRE系统错误
// 打印最近的PCRE错误,非0值表示发生错误
var_dump(preg_last_error()); // preg_last_error() == 2时,可能是回溯次数超出限制了,可修改最大回溯解决,但不可无限上调该设置以免消耗内存资源过大。默认 pcre.backtrack_limit = 1000000
ini_set('pcre.backtrack_limit', 100000000);
PHP正则式PCRE的更多相关文章
- Python正则式的基本用法
Python正则式的基本用法 1.1基本规则 1.2重复 1.2.1最小匹配与精确匹配 1.3前向界定与后向界定 1.4组的基本知识 2.re模块的基本函数 2.1使用compile加速 2.2 ma ...
- Python使用re模块正则式的预编译及pickle方案
项目上线要求当中有言论和昵称的过滤需求, 客户端使用的是python脚本, python脚本中直接利用re模块来进行正则匹配, 一开始的做法是开启游戏后, 每帧编译2条正则式, 无奈运营需求里面100 ...
- 正则双重过滤 /// splitKey1 第一个正则式匹配 /// splitKey2 匹配结果中再次匹配进行替
/// <summary> /// 正则双重过滤 /// splitKey1 第一个正则式匹配 /// splitKey2 匹配结果中再次匹配进行替换 /// </summary&g ...
- JavaScript正则式练习
使用正则式匹配第一个数字和最后一个数字,使用环视 str2 = 09051 : Fast Food Restaurants - Concession Stands/Snack Bars Delicat ...
- JavaScript正则式入门
正则式 正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表通常被用来检索.替换那些符合某个模式(规 ...
- 关于C#判断是否是数字的正则式
有话要说 今天我同事突然让我帮他看个问题,他说想不通为什么数据库中会有不合法的内容,我都已经用正则过滤了,并且在本地调通了的! 我问他是不是你正则有问题,他说没问题啊,前端和后端的正则是一样的,前端我 ...
- shell正则式解析身份证和手机号
cat test2.html | sed -e 's/\(^\|[^0-9]\)\(13[0-9][0-9]\{8\}\|14[579][0-9]\{8\}\|15[0-3,5-9][0-9]\{8\ ...
- iOS开发中正则式的使用
iOS开发中正则式的使用 第一:常规的使用方式 NSString *str = @"abcded111093212qweqw"; //找到内部一个即可 NSString *patt ...
- sas正则式之prxparen
sas正则式之prxparen 今天还是要继续正则式的内容,这周的内容是prxparen函数,这个函数我个人觉得特别有用,是因为他和"|"结合使用可以同时容纳很多种情况的字符串. ...
随机推荐
- MFC鼠标单击截获鼠标双击事件,且无法记录单击的数据的解决方案
遇到的问题: 鼠标点击会截断鼠标双击的事件,无法保存椭圆的数据.也就是说双击执行的过程是OnLButtonDown,OnLButtonUp,OnLButtonDblClk,OnLButtonUp.并不 ...
- C#中DataGridView动态添加行及添加列的方法
http://www.jb51.net/article/72259.htm Datagridview添加列: ? 1 2 3 4 5 DataGridViewTextBoxColumn acCode ...
- jquery获取select选中的值
http://blog.csdn.net/renzhenhuai/article/details/19569593 误区: 一直以为jquery获取select中option被选中的文本值,是这样写的 ...
- ubuntu16编译安装mysql5.7
安装环境: linux版本: ubuntu-16.04.3-desktop-amd64 mysql版本:mysql-boost-5.7.20.tar.gz 下载地址:https://dev.mysql ...
- Hibernate学习笔记(5)---Query接口
Hibernate中具有三种检索方式(HQL,QBC,SQL) Query接口 一个查询接口,用于向数据库中查询对象.并控制执行查询的过程.Query接口内封装了一个HQL查询语句. 举个栗子 //查 ...
- Python2和Python3中的字符串编码问题解决
Python2和Python3在字符串编码上是有明显的区别. 在Python2中,字符串无法完全地支持国际字符集和Unicode编码.为了解决这种限制,Python2对Unicode数据使用了单独的字 ...
- 第十一章:Python の 网络编程基础(三)
本課主題 多线程的创建和使用 消息队列的介绍 Python 操作 memached 和 redis 实战 本周作业 消息队列的介绍 对列是在内存中创建的,如果整个进程里的程序运行完毕之后会被清空,消息 ...
- webapi框架搭建-创建项目(三)-webapi owin
上一篇:创建项目(二) 在上一篇里,我们已经创建好了webapi应用,并已经部署到iis里,本篇讲如何用owin自宿主或是iis宿主来部署webapi应用. owin介绍 传统的asp.net网站只能 ...
- virtuoso数据库的安装方法
数据库virtuoso有两种安装配置方式 第一种就是直接在系统中默认安装,拷贝virtuoso的安装文件,直接默认安装. 第二种是配置安装方式 参考地址:http://vos.openlinksw.c ...
- SQL常用增删改查语句
1增 1.1[插入单行]insert [into] <表名> (列名) values (列值)例:insert into Strdents (姓名,性别,出生日期) values ('开心 ...