PHP 得益于其简单易学的特性,从上世纪 90 年代一直流行至今。
对于本文所要讲到的正则表达式,PHP 也有相当完备的支持,甚至它提供了至少三套独立的正则引擎:

  • preg - Perl Regular Expressions
  • ereg - Extended Regular Expressions
  • bm_ereg

由于 preg 在通常情况下速度与功能都要优于另外两者,所以本系列主要介绍 preg 引擎。

preg 属于 NFA 流派,是一组 Perl 兼容正则表达式 (PCREPerl 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 之前的换行符,除非使用了模式修饰符 m
    • S: 启用 PCREstudy 优化尝试

在表达式内部允许模式修饰符单独出现,来启用或停用某些特性,例如 (?i) 和 ` (?-i) 。他们的作用持续到对应的结束括号,如果不存在则持续到正则表达式末尾。当然,你也可以使用***模式修饰范围***例如 (?i:…)(?-SM:…)`,这里不做过多解释。