一、php正则简介
PHP中有两套正则匹配规则,一套基于POSIX,一套基于PCRE(英文全称:Perl Compatible Regular Expressions;翻译后就是“perl兼容正则表达式”,简称PCRE正则);自 PHP 5.3.0起, POSIX 正则表达式扩展被废弃,所以目前一般说PHP正则就是指PCRE正则。
PHP中主要的的正则表达式函数如下:
1.1、正则替换函数
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
函数功能:搜索subject中匹配pattern的部分, 以replacement进行替换。
此函数还有变体:
mixed preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )
这个函数的行为除了 可以指定一个 callback 替代 replacement 进行替换 字符串的计算,其他方面等同于 preg_replace()
还有一个类似的函数:
mixed preg_filter ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
preg_filter()等价于preg_replace() 除了它仅仅返回(可能经过转化)与目标匹配的结果
1.2、执行一个正则匹配
int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
搜索subject与pattern给定的正则表达式的一个匹配。
此函数也有类似函数:
int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )
搜索subject中所有匹配pattern给定正则表达式 的匹配结果并且将它们以flag指定顺序输出到matches中。
执行一个全局正则表达式匹配。
1.3、通过一个正则表达式分隔字符串
array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )
通过一个正则表达式分隔给定字符串。
1.4、其他正则函数
还有几个函数就不再详细介绍了:
array preg_grep ( string $pattern , array $input [, int $flags = 0 ] ) mixed preg_filter ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) string preg_quote ( string $str [, string $delimiter = NULL ] )
二、正则表达式的语法规则
汇总知识点
元字符 | 含义或用法 |
^ |
匹配字符串的开始位置标记 |
$ | 匹配字符串的结束位置标记 |
\ | 转义字符;将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。 |
* |
匹配前面的子表达式零次或多次 |
+ |
匹配前面的子表达式一次或多次 |
? |
匹配前面的子表达式零次或一次 |
{n} |
n 是一个非负整数。匹配确定的 n 次 |
{n,} |
n 是一个非负整数。至少匹配n 次 |
{n,m} |
m 和 n 均为非负整数,其中n <= m ,表示最少匹配 n 次且最多匹配 m 次 |
. |
匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
[xyz] |
字符集合。匹配所包含的任意一个字符 |
[^xyz] |
负值字符集合。匹配未包含的任意字符,与前一个[xyz]意义刚好相反。 |
[a-z] |
字符范围。匹配指定范围内的任意字符;匹配a到z的所有小写字母;同理取反[^a-z] |
\b |
匹配一个单词边界,也就是指单词和空格间的位置;这个多用于英文语句中的单词与单词间的空白匹配 |
\B |
匹配非单词边界;与\b意义相反 |
\d |
匹配一个数字字符。等价于 [0-9];同理取反\D (注意大小写,后续不再提示) |
\f |
匹配一个换页符。等价于 \x0c 和 \cL |
\n |
匹配一个换行符。等价于 \x0a 和 \cJ |
\r |
匹配一个回车符。等价于 \x0d 和 \cM |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v];同理取反\S |
\t |
匹配一个制表符。等价于 \x09 和 \cI |
\v |
匹配一个垂直制表符。等价于 \x0b 和 \cK |
\w |
匹配数字、字母和下滑线(也就是英文单词的构成成分)等价于[A-Za-z0-9_];同理取反\W |
三、逆向引用、子模式和模式修饰符
3.1、逆向引用
PHP正则表达式中将匹配成功的模式中的某些特定部分进行存储,提供以后使用这些特定部分的能力。在一个正则表达式模式或部分模式两边添加圆括号()
包裹划分开来,就可以把这部分表达式存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容按顺序存储;存储子匹配的缓冲区编号从1开始,连续编号至最大99个子表达式。每个缓冲区都可以使用\n
或$n
或${n}
来表示其引用,其中n为1至99的阿拉伯数字,用来按顺序标识特定缓冲区。这种模式就叫逆向引用(或反向引用、后向引用)。
逆向引用主要出现在正则替换中。
例如:去除Html标签中的属性,留意preg_replace函数第二个参数。
<?php $content = '<p style="text-align:center;" onclick="alert("crsf attack!");">测试段落</p>'; $content = preg_replace('/<(\w+)\s+[^>]+>/','<${1}>', $content); ###$content变量过滤后应该是如下内容: #<p>测试段落</p>
3.2、子模式
正则表达式匹配模式符中使用圆括号()
包裹划分开来产生的部分称为子组(子模式),子组通过圆括号分隔界定,并且它们可以嵌套;将一个模式中的一部分标记为子组(子模式)主要是来做两件事情:
1、将可选分支局部化。比如,模式cat(arcat|erpillar|)
匹配cat
、cataract
、caterpillar
中的一个,如果没有圆括号的话,它匹配的则是cataract
、erpillar
以及空字符串。
2、将子组设定为捕获子组。上述“逆向引用”中括号实现的子模式分组就是实现了这个捕获子组的功能。
子模式中圆括号履行的两种功能并不总是有用的。我们经常会有一种需求需要使用子组进行分组, 但又不需要(单独的)捕获它们。 在子组定义的左括号后面紧跟?:
字符串会使得该子组不被单独捕获, 并且不会对其后子组序号的计算产生影响。
3.3、模式修饰符
正则表达式的模式修饰符:即在正则表达式中可以改变正则表达式特性的修饰性符号。
正则表达式的贪婪模式,以例子来说明比较形象一点:假设我们要匹配以字母a
开头字母b
结尾的字符串,但是需要匹配的字符串在a
后面含有很多个b
,比如abbbbbbbbbbbbbbbbb
,那正则表达式是会匹配第一个b
还是最后一个b
呢?如果你使用了贪婪模式,那么会匹配到最后一个b
,反之只是匹配到第一个b
。也就是说贪婪模式是一种正则表达式中尽可能多的匹配模式。
i
:如果在修饰符中加上"i",则正则将会取消大小写敏感性,即"a"和"A" 是一样的。
m
:默认的正则开始^
和结束$
是对于整个字符串,如果在修饰符中加上"m",那么开始和结束将会是指字符串的每一行:每一行的开头就是^
结尾就是$
。
s
:如果在修饰符中加入"s",那么默认的"."代表除了换行符以外的任何字符将会变成任意字符,也就是包括换行符!
x
:如果加上该修饰符,表达式中的空白字符将会被忽略,除非它已经被转义。
e
:本修饰符仅仅对于 preg_replace()
函数中的replacement参数有用,代表在replacement中作为PHP代码。这个特性在PHP5.5中被废弃,已建议使用 preg_replace_callback()
代替。
A
:如果使用这个修饰符,那么表达式必须是匹配的字符串中的开头部分。比如说"/a/A"匹配"abcd"。
E
:与"m"相反,如果使用这个修饰符,那么"$"将匹配绝对字符串的结尾,而不是换行符前面,默认就打开了这个模式。
U
:和问号的作用差不多,用于设置"贪婪模式"。
四、实际应用举例
3.1、匹配html标签中的标记
也就是匹配由尖括号包裹起来的标签,如匹配<p>(也会匹配<p style="text-indent:2em">之类的有属性的p标签)
<p[^>]+>
3.2、去除html源代码中的换行符、制表符、回车等符号
$str=preg_replace("/[\t\n\r]+/","",$str);
3.3、效验字符串全部由数字构成;这种匹配不一定表示字符串是自然数,因为可能会是0开头
/^[0-9]{1,20}$/
3.4、去除html字符串中的所有js代码
##先去除所有script标签和标签内的js代码 $content = preg_replace('/<script(.*?)<\/?script>/is', "", $content); ##再去除所有标签中的使用属性实现的js事件----有误杀,style、id、class等 $content = preg_replace('/<(\w+)\s+[^>]+>/', '<${1}>', $content);
上述第2行代码中,将存在误杀,可以修改下匹配条件,删除掉特定的诸如onclick="xxx"、onmouseover="xxx"等属性,而保留诸如id、class、data-xx、value等属性。
3.5、其他的正则汇总
- "^\d+$" //非负整数(正整数 + 0)
- "^[0-9]*[1-9][0-9]*$" //正整数
- "^((-\d+)|(0+))$" //非正整数(负整数 + 0)
- "^-[0-9]*[1-9][0-9]*$" //负整数
- "^-?\d+$" //整数
- "^\d+(\.\d+)?$" //非负浮点数(正浮点数 + 0)
- "^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$" //正浮点数
- "^((-\d+(\.\d+)?)|(0+(\.0+)?))$" //非正浮点数(负浮点数 + 0)
- "^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$" //负浮点数
- "^(-?\d+)(\.\d+)?$" //浮点数
- "^[A-Za-z]+$" //由26个英文字母组成的字符串
- "^[A-Z]+$" //由26个英文字母的大写组成的字符串
- "^[a-z]+$" //由26个英文字母的小写组成的字符串
- "^[A-Za-z0-9]+$" //由数字和26个英文字母组成的字符串
- "^\w+$" //由数字、26个英文字母或者下划线组成的字符串
- "^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$" //email地址
- "^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$" //url
- /^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日
- /^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$/ // 月/日/年
- "^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$" //Emil
- "(d+-)?(d{4}-?d{7}|d{3}-?d{8}|^d{7,8})(-d+)?" //电话号码
- "^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$" //IP地址
- ^([0-9A-F]{2})(-[0-9A-F]{2}){5}$ //MAC地址的正则表达式
-
^[-+]?\d+(\.\d+)?$ //值类型正则表达式
不错的