《精通正则表达式》学习笔记(六)


PHP 的正则流派

  • PHP 的三种正则引擎是 pregcregmb_ereg
  • 在默认情况下,preg 套件的正则表达式是以字节为单位的,所以「\C」默认等价于「(?d:.)」,由 s 修饰的点号。不过,如果使用了修饰符 u,则 preg 套件就会以 UTF-8 字母为单位,也就是说,一个字符可能由 6 个字节组成。即使这样,「\C」仍然匹配单个字节。
  • \z」和「\Z」都能够匹配字符串的末尾,而「\Z」同样能够匹配最后的换行符。
  • $」的意义取决于模式修饰符 mD:如果没有设定任何修饰符,「$」等价于「\Z」(在字符串结尾的换行符,或者是字符串结尾);如果使用了 m,则它能够匹配内嵌的换行符,如果使用了模式修饰符 D,它能够匹配「\z」(只有在字符串的结尾)。如果同时设置了 mD,则忽略 D
  • PHP 正则引擎的处理方式完全是程序式的。

Preg 函数接口

函数 用途
preg_match 测试正则表达式能否在字待串中找到匹配,并提取数据
preg_match_all 从字苻串中提取数据
preg_replace 在字待串的副本中替换匹配的文本
preg_replace_callback 对字特事中的每处匹配文本调用处理函数
preg_split 将字苻串切分为子串数组
preg_grep 选出数组中能/不能由表达式匹配的元素
preg_quote 转义字符串中的正则表达式元字符

pattern 参数

  • patten 参数是包含在一对斜线(分隔符)里头的参数。分隔符后面是模式修饰符。其参数的组成:
    1. 分隔符
    2. 正则表达式
    3. 模式修饰符

分隔符

  • preg 引擎要求正则表达式两端必须有分隔符,因为设计者希望它看起来更像 Perl,尤其在模式修饰符的使用方法上更是如此。
  • 可以使用除了字母、数字、反斜线和空白字符之外的任何 ASCI 字符做分隔符。最常见的是一对斜线,或者两个 !#
  • 分隔符的选取应该考虑实际情况,避免产生嵌套。如正则表达式内如果存在括号 (),则应该避免使用 () 作为分隔符。

正则表达式

  • 因为正则表达式很有可能包含反斜线,所以在以字符串文字方式提供 pattern 参数时,最好使用 PHP 的单引号字符串,这样可以省略许多额外的转义。

模式修饰符

  • 表达式内部的模式修饰符:在正则表达式内部,模式修饰符可以单独出现,来启用或停用某些特性,其作用范围持续到对应的结束括号。
标准修饰符 用途 说明
i (?!) 忽略大小写
m (?m) 增强的行铺点模式
s (?s) 点号通配模式
x (?x) 宽松排列和注释模式
PHP 特有修饰符 用途 说明
u 在 UTF-8 编码中,非 ASCI 字符以多个字节来存储,使用 u 修饰符能够以 UTF-8 编码处理正则表达式和目标字符串,确保多个字节会被作为单个字符来处理。处理时也不会修改数据,只是更改正则引擎处理数据的方式
S 启用 PCRE 的 “study” 优化特性,预先分析正则表达式,在某些顺利的情况下,在尝试匹配时速度会大大提升
D 把每个「$」替换为「\z」,即「$」匹配字符串的末尾,而不是字符串之内的换行符。
A 把匹配锚定在第一次尝试的位置
X (?X) 启用 PCRE “额外功能(extra stuff)”,报告非无法识别的反斜线序列
e 将 replacement 作为 PHP 代吗(只用于 preg_replace)
U (?U) 交换「*」和「*?」的匹配优先含义,建议不使用

Preg 函数罗列

preg_match

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
  • $matches 末尾的空字符串都会被忽略。
  • 使用命名捕获会使代码更易读,但使用了命名捕获,按数字编号的捕获仍然会插人 $matches。所以不推荐同时使用命名和数字编号来访问 $matches 的元素。

命名捕获

  • 参数 flags 可使用参数值:PREG_OFFSET_CAPTURE 使第 1 个元素是匹配的文本,第 2 个元素是这段文本在目标字符串中的偏移值。其通常按照字节来计数。

preg_match_all

int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )
  • 每个匹配都会创建一个包含匹配数据的数组,所以最后 matches 变量就是一个二维数组,其中的每个子数组对应一次匹配。
  • 参数 flags 可使用参数值 PREG_PATTERN_ORDERPREG_SET_ORDER 用于制定排列方式:
类型 标志位 说明及示例
按分组号 PREG_PATTERN_ORDER 将各次匹配中同样编号的分组编在一起
堆叠 PREG_SET_ORDER 将每次匹配的数据集中保存

preg_replace

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
  • 对文本进行査找-替换的办法。
  • subject 也可以是一个字符串数组,搜索和替换是对每个字符串依次进行的。
  • patternreplacement 参数也可以是字符申数组。
  • 如果 subject 参数是数组,则依次处理数组中的每个元素,返回值也是字符串数组。
  • preg_replace 的程序要使用 each() 来按照数组的内部顺序历整个数组,而不关心它们的 keys 如何。
  • 如果 patternreplacement 数组的内部顺序不同于你希望匹配的顺序,可以使用 sort() 函数来确保每个数组的实际顺序和外表顺序是相同的。

preg_replace_callback

mixed preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )
  • replacement 参数变成了 PHP 回调函数,而不是字符串或是字符串数组。

preg_split

array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )
  • preg_split 找出目标字符串中不能由正则表达式匹配的部分。返回目标字符串中正则表达式匹配的部分別去之后的部分。相当于 PHP 中内建的简单 explode 函数,不过使用的是正则表达式,而且功能更强大。
  • limit 参数用来设定切分之后数组长度的上限。达到 limit 之后的文本内容会全部保存到最后的元素当中。
  • 参数 flags 可使用参数值:
    • PREG_SPLIT_OFFSET_CAPTURE 标志位会修改结果数组,把每个元素变为包含两个元素的数组(元素本身和它在字符串中的偏移值)。
    • PREG_SPLIT_NO_EMPTY 标志位告诉 preg_split 忽略空字符串。
    • PREG_SPLIT_DELIM_CAPTURE 标志位在结果中包含匹配的文本,以及捕获括号匹配的文本。

preg_grep

preg_grep ( string $pattern , array $input [, int $flags = 0 ] ) : array
  • preg_grep 生成 $input 数组的副本,其中只保留了 $value 能够匹配 $pattern 的元素。

preg_quote

preg_quote ( string $str [, string $delimiter = NULL ] ) : string
  • 转义正则表达式字符,向其中每个正则表达式语法中的字符前增加一个反斜线。

效率

  1. 回调函数通常要比模式修饰符 e 更快;
  2. 在太长的目标字符串中使用命名捕获必须进行更多的数据拷贝。
  3. 除非把同一个表达式应用到大规模的文本,或者大量小规模文本时,オ需要考虑模式修饰符 S