对于任何有过编程经验的人来说,他对正则表达式应该不会感到陌生。
正则表达式(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|)
匹配cat
,cataract
,caterpillar
中的一个
- 后向引用
在反斜线后面加一个大于零的数字可以引用模式前面捕获的内容,这叫做后向引用。
如果紧跟反斜线的数字小于 10, 它总是一个后向引用, 并且如果在模式中没有这么多的捕获组会引发一个错误。例如:
模式(sens|respons)e and \1ibility
将会匹配sense and sensibility
和response and responsibility
, 但不会匹配sense and responsibility
。
- 断言
一个断言就是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符。它有两种类型: 前瞻断言(从当前位置向前测试)和后瞻断言(从当前位置向后测试);每个类型又有肯定断言和否定断言之分。
所以共有以下四种断言:
1、前瞻肯定断言(?=
2、前瞻否定断言(?!
3、后瞻肯定断言(?<=
4、后瞻否定断言(?<!
例如:
\w+(?=;)
匹配一个单词紧跟着一个分号但是匹配结果不会包含分号foo(?!bar)
匹配所有后面没有紧跟bar
的foo
字符串(?<!foo)bar
用于查找任何前面不是foo
的bar
贪婪/懒惰匹配模式
当正则表达式中包含能接受重复的限定符时,默认的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。这被称为贪婪匹配。
例如:
以a.*b
来搜索aabab
时,它会匹配整个字符串aabab
。
可是我们的需求并非一直是要贪婪匹配的,有时候也会选择懒惰的匹配模式。其实在量词后面紧跟着 ?
即为懒惰模式。*?
+?
{n,m}?
皆为懒惰匹配。
例如:
以a.*?b
来搜索aabab
时,它会匹配字符串aab
和ab
。
常用的几个修饰符
-
i
忽略大小写模式 -
m
多行模式 -
s
点号通配模式 -
U
懒惰模式 -
D
结尾限制 -
u
支持 UTF-8 转义表达
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。