1

对于任何有过编程经验的人来说,他对正则表达式应该不会感到陌生。

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

平时没有系统地学习过正则表达式的知识,多数情况都是在使用到时,才会查找相关的语法来实现需求。最近对 PHP 的正则表达式进行了一次主题阅读,收获良多,特意写篇笔记记录下来。

PHP 对正则表达式的支持

PHP 中有两种类型的函数来处理正则表达式,一种是由 PCRE 库提供的函数,它们是以 preg_ 前缀开头的;另一种是 由 POSIX 扩展提供的函数,它们是以 ereg_ 前缀开头。但是从 PHP5.3.0 开始后者便不再建议使用,故而以下的知识都是针对 PCRE 模式的。

PHP 正则表达式的组成部分

PHP 中的正则表达式由以下三部分组成:

  • 分隔符
  • 表达式
  • 修饰符

例如:

/[a-zA-Z0-9-_]+/m

上面的例子当中:
字符串收尾的 / 属于正则表达式的分隔符,它可以是任意的非字母数字、非反斜线、非空白字符;
分隔符中间部分 [a-zA-Z0-9-_]+ 属于正则表达式的表达式;
正则表达式最后的部分 m 是修饰符,这里的 m 表示多行选择。

元字符

正则表达式的威力源于它可以在模式中拥有选择和重复的能力。 一些字符被赋予 特殊的涵义,使其不再单纯的代表自己,模式中的这种有特殊涵义的编码字符 称为 元字符。

元字符 含义
\ 一般用于转义字符
^ 断言目标的开始位置(或在多行模式下是行首)
$ 断言目标的结束位置(或在多行模式下是行尾)
. 匹配除换行符外的任何字符(默认)
[ 开始字符类定义
] 结束字符类定义
| 开始一个可选分支
( 子组的开始标记
) 子组的结束标记
? 作为量词,表示 0 次或 1 次匹配。位于量词后面用于改变量词的贪婪特性。 (查阅量词)
* 量词,0 次或多次匹配
+ 量词,1 次或多次匹配
{ 自定义量词开始标记
} 自定义量词结束标记
正则表达式的语法
  • 字符类(方括号)

左方括号开始一个字符类的描述,并以方中括号结束。 单独的一个右方括号没有特殊含义。如果一个右方括号需要作为一个字符类中的成员, 那么可以将它写在字符类的首字符处(如果使用了^取反, 那么是第二个)或者使用转义符。
一个字符类在目标字符串中匹配一个单独的字符; 该字符必须是字符类中定义的字符集合的其中一个, 除非使用了 ^ 对字符类取反。

例如:
[\d] 匹配所有的数字
[^\d] 匹配所有的数字之外的字符

  • 可选路径(|)

竖线字符用于分离模式中的可选路径。 竖线可以在模式中出现任意多个,并且允许有空的可选路径(匹配空字符串)。 匹配的处理从左到右尝试每一个可选路径,并且使用第一个成功匹配的。

比如:
模式 gilbert|Sullivan 匹配 gilbert 或者 sullivan

  • 子组(子模式)

子组通过圆括号分隔界定,并且它们可以嵌套。子组具有两个作用:
1、 将可选分支局部化;
2、 将子组设定为捕获子组。

比如:
模式 cat(arcat|erpillar|) 匹配 catcataractcaterpillar 中的一个

  • 后向引用

在反斜线后面加一个大于零的数字可以引用模式前面捕获的内容,这叫做后向引用。
如果紧跟反斜线的数字小于 10, 它总是一个后向引用, 并且如果在模式中没有这么多的捕获组会引发一个错误。

例如:
模式 (sens|respons)e and \1ibility 将会匹配 sense and sensibilityresponse and responsibility, 但不会匹配 sense and responsibility

  • 断言

一个断言就是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符。它有两种类型: 前瞻断言(从当前位置向前测试)和后瞻断言(从当前位置向后测试);每个类型又有肯定断言和否定断言之分。

所以共有以下四种断言:
1、前瞻肯定断言 (?=
2、前瞻否定断言 (?!
3、后瞻肯定断言 (?<=
4、后瞻否定断言 (?<!

例如:
\w+(?=;) 匹配一个单词紧跟着一个分号但是匹配结果不会包含分号
foo(?!bar) 匹配所有后面没有紧跟 barfoo 字符串
(?<!foo)bar 用于查找任何前面不是 foobar

贪婪/懒惰匹配模式

当正则表达式中包含能接受重复的限定符时,默认的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。这被称为贪婪匹配。

例如:
a.*b 来搜索 aabab 时,它会匹配整个字符串 aabab

可是我们的需求并非一直是要贪婪匹配的,有时候也会选择懒惰的匹配模式。其实在量词后面紧跟着 ? 即为懒惰模式。*? +? {n,m}? 皆为懒惰匹配。

例如:
a.*?b 来搜索 aabab 时,它会匹配字符串 aabab

常用的几个修饰符
  • i 忽略大小写模式
  • m 多行模式
  • s 点号通配模式
  • U 懒惰模式
  • D 结尾限制
  • u 支持 UTF-8 转义表达
参考链接

http://php.net/manual/zh/book...
https://regex101.com/


chenishr
238 声望11 粉丝

淡泊以明志,宁静以致远