PHP 得益于其简单易学的特性,从上世纪 90 年代一直流行至今。
对于本文所要讲到的正则表达式,PHP 也有相当完备的支持,甚至它提供了至少三套独立的正则引擎:
preg-Perl Regular Expressionsereg-Extended Regular Expressionsbm_ereg
由于 preg 在通常情况下速度与功能都要优于另外两者,所以本系列主要介绍 preg 引擎。
preg 属于 NFA 流派,是一组 Perl 兼容正则表达式 (PCRE,Perl Compatible Regular Expressions) 套件,十分完整的模拟了 Perl 语法和语义,并对拓展了许多 ereg 不具备的能力。
所有 preg 函数第一个参数均为 pattern,其中正则表达式会被一对分隔符表示(因为 preg 的作者希望它看起来更像 Perl),最后还可能跟随模式修饰符。
例如:
/<table\b/i
其中第一个 / 为分隔符,<table\b 为正则表达式,/ 为分隔符,i 为模式修饰符。
分隔符
无论是好是坏,这是一项硬性规定。我们可以使用除了下列元素外的任意 ASCII 字符作为分隔符:
- 数字
- 字母
- 反斜线
\ - 空白字符
正如前面例子中那样,分隔符成对出现,常见的有一对 /、! 或 #,此外,也可以使用:
{和}(和)<和>[和]
模式修饰符
允许出现的模式修饰符有:
- 标准修饰符:
x: 自由格式和注释模式,可以识别 ASCII 中空白字符,但不能识别 Unicode 中的空白字符,在正则表达式内部写作(?x)s: 点号通配模式,在正则表达式内部写作(?s)m: 增强的行锚点模式,在正则表达式内部写作(?m)i: 忽略大小写模式,在正则表达式内部写作(?i)
- 特有修饰符:
u: 以UTF-8读取正则表达式和目标文本X: 启用PCRE额外功能(extra stuff),目前只有一个功能就是在出现无法识别的反斜线序列时报错,在正则表达式内部写作(?X)U: 交换*和*?等的匹配优先含义,很少使用,在正则表达式内部写作(?U)e: 将replacement作为 PHP 代码(只用于preg_replace)A: 将整个匹配尝试锚定在起始位置,很少使用D: 替换$为\z,$只能匹配 EOS 而不是 EOS 之前的换行符,除非使用了模式修饰符mS: 启用PCRE的study优化尝试
在表达式内部允许模式修饰符单独出现,来启用或停用某些特性,例如 (?i) 和 (?-i)。他们的作用持续到对应的结束括号,如果不存在则持续到正则表达式末尾。当然,你也可以使用模式修饰范围例如 (?i:...)、 (?-SM:...),这里不做过多解释。