老程序员分享:Php中正则小结(一)

简介: 老程序员分享:Php中正则小结(一)

一.概念


语法模式类似perl.表达式必须用分隔符闭合,比如一个正斜杠(/).


分隔符可以是任意非字母非数字,除反斜杠()和空字节之外的非空白ascii字符


如果分隔符 在表达式中使用,需要使用反斜线进行转义。


二.组成


元字符


一个正则表达式基本组成


/原子和元字符/模式修正符 /代表定界符的一个


正则表达式的威力在于其能够在模式中包含选择和循环。它们通过使用元字符来编码在模式中,元字符不代表其自身,它们用一些特殊的方式来解析。


根据在方括号的内部还是外部分为两种。


1.方括号之外的元字符


元字符(符号)


说明


\


一般用于转义字符


^


断言目标的开始位置(或在多行模式下是行首)


$


目标的结束位置(活在多行模式下行尾)


.


匹配除换行符外任何字符(默认时)


【,】


开始,结束字符类定义


|


开始一个可选分支


( ,)


子组的开始//代码效果参考:http://www.lyjsj.net.cn/wz/art_23879.html

,结尾标记

?


作为量词,表示 0 次或 1 次匹配。位于量词后面用于改变量词的贪婪特性



量词,0 次或多次匹配


+


量词,1 次或多次匹配


{ ,}


自定义量词开始标记,结束标记


2.模式中方括号内的部分称为“字符类”


元字符


说明


\


转义字符


^


仅在作为第一个字符时,表明字符类取反


-


标记字符范围


元字符用法说明举例


1.转义(反斜线)


\后紧跟着一个非字母数字字符,则取消该字符可能具有的任何特殊含义。此种适用于字符类之中或之外。


对于非数字字母的字符,总是需要其进行原文匹配时候在它前面加一个反斜线,来代表它代表自己。


匹配 “” 时,由于其有特殊含义,所以用 “*”取消掉了其特殊含义


匹配”.”用”.”


匹配”\” 用”\”


但要注意:


反斜线在单引号字符串和双引号字符串中都有特殊含义,因此要匹配一个反斜线,模式中必须写”\\”或’\\’


2.反斜线第二种用途提供了一种对非打印字符进行可见编码的控制手段。除了二进制的0会终结一个模式外,并不会严格的限制非打印字符(自身)的出现,但是当一个模式以文本编辑器的方式编辑准备的时候,使用下面的转义序列相比比使用二进制字符会更容易。


符号


说明


\a


响铃字符(十六进制 07)


\cx


"control-x",x 是任意字符


\e


转义 (十六进制 1B)


\f


换页 (十六进制 0C)


\n


换行 (十六进制 0A)


\p{xx} (p小写)


一个符合 xx 属性的字符


\P{xx} (p大写)


一个不符合 xx 属性的字符


\r


回车 (十六进制 0D)


\t


水平制表符 (十六进制 09)


\xhh


hh十六进制编码的字符


\ddd


ddd八进制编码的字符,或者后向引用


\040


空格的另外一种用法


\40


当提供了少于40个子组时也认为是空格。


\7


始终是后向引用


\11


可能是后向引用,也可能是制表符


\011


总是一个制表符


\0113


一个制表符紧跟着一个3(因为每次最多只读取3个8进制位


\113


八进制113代表的字符


\377


8进制377是10进制255, 因此代表一个全1的字符


\81


一个后向引用或者一个二进制 0 紧跟着两个数字 8 和 1(因为8不是8进制有效数字)


3.反斜线第三种用法,描述特定的字符类


符号


说明


\d


任意十进制数字


\D


任意非十进制数字


\h


任意水平空白字符(从php 5.2.4起)


\H


任意非水平空白字符(从php 5.2.4起)


\s


任意空白字符


\S


任意非空白字符


\v


任意垂直空白字符(since PHP 5.2.4)


\V


任意非垂直空白字符(since PHP 5.2.4)


\w


任意单词字符


\W


任意非单词字符


上面每一对转义序列都代表了完整字符集中两个不相交的部分, 任意字符一定会匹配其中一个,同时一定不会匹配另外一个。


第四种用法 简单的断言


\b


单词边界 注意在字符类中是退格


\B


非单词边界


\A


目标的开始位置(独立于多行模式)


\Z


目标的结束位置或结束处的换行符(独立于多行模式)


\z


目标的结束位置(独立于多行模式)


\G


在目标中首次匹配位置


\A,\Z,\z断言不同于传统的^和$


因为他们永远匹配目标字符串的开始和结尾,而不会受模式修饰符的限制


\Z和 \z之间的不同在于当字符串结束字符时换行符时 \Z 会将其看做字符串结尾匹配, 而 \z 只匹配字符串结尾。


代码1


$p='#\A【a-z】{3}#m';


$str='abc


defg


hijkl';


preg_match_all($p,$str,$all);


print_r($all);


发现后面加不加模式修正符m结果都一样


只匹配到abc


而代码2:


$p='#^【a-z】{3}#m';


$str='abc


defg


hijkl';


preg_match_all($p,$str,$all);


print_r($all);


不加m只匹配abc


加上之后匹配了abc,def,hij


果真,\A不受模式修正符的影响


同理可比较$与\Z


\Z与\z


代码3


$p='#【a-z】\Z#';


$str="a\n";


preg_match_all($p,$str,$all);


print_r($all);


模式修正为\E时匹配到a


当模式修正为\e时,由于它只匹配到字符的结束,不认换行符,所以匹配不到任何东西


G 断言在指定了$offset 参数的 preg_match()() 调用中, 仅在当前匹配位置在匹配开始点的时候才是成功的


当 $offset 的值不为 0 的时候, 它与 \A 是不同的。


参见php手册


自 PHP 4.3.3开始, \Q和 \E 可以用于在模式中忽略正则表达式元字符.


即把有特殊含义的字符放在\Q与\E之间


如代码4


$p='#\w+\Q.$.\E$#';


$str="a.$.";


preg_match_all($p,$str,$all);


print_r($all);


匹配到 a.$.


自 PHP 5.2.4 开始。 \K 可以用于重置匹配。 比如, foot\Kbar 匹配”footbar”。 但是得到的匹配结果是 ”bar”。但是, \K 的使用不会干预到子组内的内容, 比如 (foot)\Kbar 匹配 ”footbar”,第一个子组内的结果仍然会是 ”foo”。译注: \K 放在子组和子组外面的效果是一样的。


\p{Lu}匹配大写字母


句点


在字符类外部


\C可以被用于匹配单字节, 也就是说在UTF-8模式下,句点可以匹配多字节字符


Character classes


alnum


字母和数字


alpha


字母


ascii


0 - 127的ascii字符


blank


空格和水平制表符


cntrl


控制字符


digit


十进制数(same as \d)


graph


打印字符, 不包括空格


lower


小写字母


print


打印字符,包含空格


punct


打印字符, 不包括字母和数字


space


空白字符 (比\s多垂直制表符)


upper


大写字母


word


单词字符(same as \w)


xdigit


十六进制数字


比如'#【【:upper:】】#'匹配大写字母


'#【【:alpha:】】#' 匹配字母


可选路径|


竖线字符用于分离模式中的可选路径。 比如模式gilbert|Sullivan匹配 ”gilbert” 或者 ”sullivan”。 竖线可以在模式中出现任意多个,并且允许有空的可选路径(匹配空字符串)。 匹配的处理从左到右尝试每一个可选路径,并且使用第一个成功匹配的。 如果可选路径在子组(下面定义)中, 则”成功匹配”表示同时匹配了子模式中的分支以及主模式中的其他部分。


代码5


$p='#p(hp|ython|erl)#';


$str="php python perl";


preg_match_all($p,$str,$all);


print_r($all);


子组(子模式)


子组通过圆括号分割界定,并且它们可以嵌套,主要有以下两种用法与功能


1.将可选分支局部化。比如


模式 p(hp|ython|erl) 匹配php,python,perl中的一个


2.将子组设定为捕获子组。


整个模式匹配后, 左括号从左至右出现的次序就是对应子组的下标(从 1 开始), 可以通过这些下标数字来获取捕获子模式匹配结果。


代码6


$p='#(\d)#';


$str="abc123";


$r=preg_replace($p,'\1',$str);


echo $r;


但当只想分组而又不想捕获时


在子组定义的左括号后面紧跟字符串 ”?:” 会使得该子组不被单独捕获, 并且不会对其后子组序号的计算产生影响


代码7:匹配数字 把数字改为红色的


$p='#.(?:\d).(【a-z】)#U';


$str="3df5g";


$r=preg_replace($p,'\1',$str);


echo $r;


如果匹配数字的模式不加?:


那么\1代表的就是匹配就是数字,加上后只是分组不捕获了,\1就代表捕获的字母了


为了方便简写,如果需要在非捕获子组开始位置设置选项, 选项字母可以位于 ? 和 : 之间,比如:


(?i:saturday|Sunday)


(?:(?i)saturday|Sunday)


其中i是模式修正符,忽略大小写


上面两种写法实际上是相同的模式。因为可选分支会从左到右尝试每个分支, 并且选项没有在子模式结束前被重置, 并且由于选项的设置会穿透对后面的其他分支产生影响,因此, 上面的模式都会匹配 ”SUNDAY” 以及 ”Saturday”。


在 PHP 4.3.3 中,可以对子组使用 (?Ppattern) 的语法进行命名。 这个子模式将会在匹配结果中同时以其名称和顺序(数字下标)出现, PHP 5.2.2中又增加了两种味子组命名的语法: (?pattern) 和 (?’name’pattern)。不能双引号


代码如下8:


$p="#.(?【a-z】{3})(?'digit'\d{3}).#";


$str="abc123111def111g";


preg_match_all($p,$str,$arr);


print_r($arr);


结果:


有时需要多个匹配可以在一个正则表达式中选用子组。 为了让多个子组可以共用一个后向引用数字的问题, (?\语法允许复制数字。 考虑下面的正则表达式匹配Sunday:


(?:(Sat)ur|(Sun))day


这里当后向引用 1 空时Sun 存储在后向引用 2 中. 当后向引用 2 不存在的时候 Sat 存储在后向引用 1中。 使用 (?|修改模式来修复这个问题:


代码9:


$p='#(?:(sat)ur|(sun))day#';


$str="sunday saturday";


preg_match_all($p,$str,$arr);


print_r($arr);


结果:


(?|(Sat)ur|(Sun))day


使用这个模式, Sun和Sat都会被存储到后向引用1中。


在看这个模式前先看以2个下代码


代码10-1


$p='#(a|b)\d#';


$str="b2a1";


preg_match_all($p,$str,$arr);


print_r($arr);


结果是:Array


(


【0】 => Array


(


【0】 => b2


【1】 => a1


)


【1】 => Array


(


【0】 => b


【1】 => a


)


)


代码10-2


$p='#((a)|b)\d#';


$str="b2a1";


preg_match_all($p,$str,$arr);


print_r($arr);


结果:


Array


(


【0】//代码效果参考:http://www.lyjsj.net.cn/wz/art_23877.html

=> Array

(


【0】 => b2


【1】 => a1


)


【1】 => Array


(


【0】 => b


【1】 => a


)


【2】 => Array


(


【0】 =>


【1】 => a


)


)


对10-2代码:


第一次完整匹配到的内容是b2,所以包括匹配内容b的括号即为其第一个子模式是即为b,第二个子模式由于(a)没有匹配,所以为空


第二次完整匹配到a1,其第一个子模式为a,第二次的由于((a)|b)是外层大括号里包含的


代码10-3:


$p='#((a)|(b))\d#';


$str="b2a1";


preg_match_all($p,$str,$arr);


print_r($arr);


结果:


Array


(


【0】 => Array


(


【0】 => b2


【1】 => a1


)


【1】 => Array


(


【0】 => b


【1】 => a


)


【2】 => Array


(


【0】 =>


【1】 => a


)


【3】 => Array


(


【0】 => b


【1】 =>


)


)


代码10-4:


$p='#(?:(a)|(b))//代码效果参考:http://www.lyjsj.net.cn/wz/art_23875.html

\d#';

$str="b2a1";


preg_match_all($p,$str,$arr);


print_r($arr);


结果:


Array


(


【0】 => Array


(


【0】 => b2


【1】 => a1


)


【1】 => Array


(


【0】 =>


【1】 => a


)


【2】 => Array


(


【0】 => b


【1】 =>


)


)


代码10:


$p='#(?|(sat)ur|(sun))day#';


$str="sunday saturday";


preg_match_all($p,$str<

相关文章
|
6月前
|
SQL 监控 安全
代码审计-PHP原生开发篇&SQL注入&数据库监控&正则搜索&文件定位&静态分析
代码审计-PHP原生开发篇&SQL注入&数据库监控&正则搜索&文件定位&静态分析
|
7月前
|
PHP
php 正则匹配 常用的 规则(一) 匹配form表单
php 正则匹配 常用的 规则(一) 匹配form表单
35 0
|
7月前
|
PHP
php 正则匹配 规则(二)匹配form表单 示例
php 正则匹配 规则(二)匹配form表单 示例
39 0
|
Java PHP C++
PHP快速入门09-正则相关,附一定要学会的20个高频使用案例
PHP快速入门09-正则相关,附一定要学会的20个高频使用案例
PHP正则匹配中文
PHP正则匹配中文
|
存储 JavaScript 前端开发
JavaScript与PHP中正则
有个在线调试正则的工具,点击查看工具。下面的所有示例代码,都可以在codepen上查看到。
JavaScript与PHP中正则
|
PHP Perl
PHP中文正则
编辑个人资料模块规则验证
148 0
PHP中文正则
|
PHP
PHP手机号验证正则
PHP手机号验证正则
127 0
PHP正则匹配字符串只能包含数字、字符串、下划线
//列子 $string = ' abc_123@c c!'; //去除字符串所有空格(结果为'abc_123@cc!') $string = preg_replace('# #','',$string); //验证字符串是否只包含数字和字母以及下划线 $res = preg_match("/^[a-zA-Z0-9_]+$/",$string); //如果不符合正则表达式规则,则抛出异常 if (!$res){ //自定义异常类 throw new OperationException([ 'errorCode'=>999,
|
PHP
PHP利用正则实现手机号中间四位****
PHP利用正则实现手机号中间四位****
117 0