飞机的 PHP 学习笔记四:正则表达式

前言

最近在系统的学习 PHP ,参考的资料是《PHP编程》+ 官方文档(如果你有好的学习资料,欢迎推荐给我)。虽然这本《PHP编程》是基于 PHP5 的,但我笔记里的代码,全部在 PHP 7.2 的环境里测试过,是能够运行的。另,本笔记中只记录我模糊不清的知识。

基础

. : 匹配任意单个字符

var_dump(preg_match("/c.t/", "cat")); // true
var_dump(preg_match("/c.t/", "c t")); // true
var_dump(preg_match("/c.t/", "b t")); // false
var_dump(preg_match("/c.t/", "ct")); // false

匹配特殊字符(元字符)要使用反斜杠进行转义

var_dump(preg_match("/\\$5\\.00/", "Your bill is $5.00 exactly")); // true
var_dump(preg_match("/$5.00/", "Your bill is $5.00 exactly")); // false

正则表达式中,有三种基本的抽象模式:

  • 在字符串中可以出现的字符集(字母、数字和特殊的标点符号)
  • 可选择的字符串集合(例如“com”、“edu”、“net”)
  • 在字符串中重复的序列(至少一个但是不多于5个数字字符)

锚( anchor )将匹配限制在字符串中的特定位置(锚不匹配目标字符串中的实际字符)

匹配
^ 字符串开始
$ 字符串结尾
[[:<:]] 单词开始
[[:>:]] 单词结尾
\b 单词边界(\w和\W之间或者字符串的开头、结尾)
\B 非单词边界(\w\w之间或者\W\W之间)
\A 字符串开始
\Z 字符串结尾,或者换行符 \n 之前
\z 字符串结尾
^ 一行的开头(如果/m标签生效,换行符\n后面)
$ 一行的结尾(如果/m标签生效,换行符\n前面)

^ : 匹配到字符串的开头

preg_match("/^cow/", "Dave was a cowhand"); // false
preg_match("/^cow/", "cowabunga"); // true

$ : 匹配到字符串的结尾

var_dump(preg_match("/cow$/", "Dave was a cowhand")); // false
var_dump(preg_match("/cow$/", "Don't have a cow")); // true

字符类

通过中括号包含可接受的字符类

描述 扩展
[:alnum:] 字母和数字字符 [0-9a-zA-Z]
[:alpha:] 字母字符 [a-zA-Z]
[:ascii:] 7位的 ASCII 码 [\x01-\x7F]
[:black:] 水平空白符 [ \t]
[:cntrl:] 控制字符 [\x01-\x1F]
[:digit:] 数字 [0-9]
[:graph:] 用墨水打印的字符 [^\x01-\x20]
[:lower:] 小写字母 [a-z]
[:print:] 可打印的字符(图形类、空格和制表符) [\t\x20-\xFF]
[:punct:] 任意标点符号 [-!”#$%^’()*+,./:;<=>?@[\]^_{|}~]
[:space:] 空白字符 [\n\r\t \x0B]
[:upper:] 大写字母 [A-Z]
[:xdigit:] 十六进制数 [0-9a-fA-F]
\s 空白 [\r\n \t]
\S 非空白 [^\r\n \t]
\w 单词字符 [0-9a-zA-Z_]
\W 非单词字符 [^0-9a-zA-Z_]
\d 数字 [0-9]
\D 非数字 [^0-9]
var_dump(preg_match("/c[aeiou]t/", "I cut my hand")); // true
var_dump(preg_match("/c[aeiou]t/", "What cart")); // false 中间由两个字符
var_dump(preg_match("/c[aeiou]t/", "14ct gold")); // false 中间没有字符
//在字符类开头使用 ^ 来否定这个字符类
var_dump(preg_match("/c[^aeiou]t/", "I cut my hand")); // false
//用连接符( - )定义一个字符范围
var_dump(preg_match("/[0-9]%/", "25%")); // true
var_dump(preg_match("/[a-zA-Z]!/", "stop!")); // true
var_dump(preg_match("/[a-zA-Z]!/", "stop")); // false

选择性

使用竖线( | )字符在正则表达式中指定可选择的部分

var_dump(preg_match("/^([a-z]|[0-9])/", "The quick brown fox")); // false
var_dump(preg_match("/^([a-z]|[0-9])/", "jumped over`")); // true

重复序列

量词 意义
? 0 次或 1 次
* 0 次或多次
+ 1 次或多次
{ n } 出现 n 了
{ n , m } 最少 n 次,不超过 m 次
{ n , } 最少 n 次
var_dump(preg_match("/ca+t/", "caaaaaaaaaat")); // true

子模式

使用小括号把正则表达式组合在一起,作为一个单独的单元来处理。可以指定第三个参数传递给匹配函数,第三个参数将会被返回一个数组。数组第 0 个元素设置为匹配的整个字符串,第一个元素是与子模式匹配的第一个子字符串,第二个元素是与子模式匹配的第二个子字符串,以此类推。

如果你不想捕获匹配到的文本,可以用(?:subpattern)的结构来实现

preg_match("/([0-9]+)([a-z]+)/", "1234yii", $good);
var_dump($good[1]); // 1234
var_dump($good[2]); // yii
preg_match("/(?:[0-9]+)([a-z]+)/", "1234yii", $good);
var_dump($good[1]); // yii

量词和贪婪

正则表达式中的量词是贪婪的,所以提供了一种模式来使得量词支持最少匹配模式。

贪婪量词 非贪婪量词
? ??
* *?
+ +?
{ n } { n }?
{ n , } { n , }?
{ n , m } { n , m }?
var_dump(preg_match("/(<.*>)/", "do <b>not</b> press the button", $match));
var_dump($match[1]); // <b>not</b>
var_dump(preg_match("/(<.*?>)/", "do <b>not</b> press the button", $match));
var_dump($match[1]); // <b>

逆向引用

使用逆向引用 \1 ,来引用某个模式里面匹配到的第一个文本,\2 来引用第二个,以此类推。

preg_match("/([[:alpha:]]+)\s+\\1/", "Paris in the the spting", $good); // 这里的\\1 就相当于 ([[:alpha:]]+)
var_dump($good); // 结果返回如下
array(2) {
  [0]=>
  string(7) "the the"
  [1]=>
  string(3) "the"
}

后缀选项

正则表达式允许你把字符放在正则表达式的后面,从而改变表达式的解析、行为或者匹配方式。

修饰符 意义
/regexp/i 匹配大小写
/regexp/s 使句点匹配任何字符,包括换行符\n
/regexp/x 去掉空白和注释
/regexp/m 使得( ^ )匹配换行符\n之后的内容,( $ ) 匹配换行符\n之前的内容
/regexp/e 如果替换字符串是 PHP 代码,使用 eval() 执行该代码,得到实际替换的字符串
/regexp/U 颠倒子模式的贪婪性。* 和 + 尽可能少地匹配而不是尽可能多
/regexp/u 把模式字符串当作 UTF-8 编码
/regexp/X 如果一个反斜杠之后跟着没有特殊意义的字符,则产生一个错误
/regexp/A 把锚定位在字符串的开头就像模式中由 ^ 一样
/regexp/D 使 $ 字符仅匹配一行的末尾
/regexp/S 使表达式解析器更小心地检查模式的结构,使得第二次运行时(如在一个循环中),加快速度
$message = <<< END
To: you@youcorp
From: me@mecorp
Subject: pay up

pay me or else!
END;
var_dump(preg_match("/^subject: (.*)/im", $message, $good)); // true
var_dump($good[1]); // pay up

除了在模式结束分隔符之后指定模式选项之外,还可以在一个模式内部指定仅运行于部分模式的选项。语法为:(?flags:subpattern)

var_dump(preg_match("/I like (?ix:ph p)/", "I like pHp")); // true

正则表达式的相关函数

匹配

  • preg_match(pattern, string[, &matches]):int : 搜索 stringpattern 给定的正则表达式的一个匹配。如果提供 matches 参数,它将被填充为搜索结果,$matches[0] 将包含完整模式匹配到的文本,$matches[1] 将包含第一个捕获子模式匹配到的文本,以此类推。
  • perg_match_all() : 与 preg_match() 参数相同,不同的是 preg_match() 在第一次匹配后停止搜索,preg_match_all() 会一直搜索到结尾。

替换

  • preg_replace(pattern, replacement, subject[, limit = -1]):mixed : 搜索 subject 中匹配 pattern 的部分,以 replacement 进行替换。limit : 每个模式在每个 subject 上进行替换的最大次数。默认是 -1 (无限)。
  • preg_replace_callback(pattern, callable, subject[, limit = -1]):mixed : 与 preg_replace() 不同的是,可以指定一个 callback 替代 replacement 进行替换字符串的计算。

拆分

  • preg_split(pattern, subject[, limit=-1[, flags=0]]):array : 通过一个正则表达式 pattern 分割字符串 subject

使用正则表达式过滤数组

  • preg_grep(pattern, array[, flags=0]):array : 返回给定数组 array 中模式 pattern 匹配的元素组成的数组。

引用正则表达式

  • preg_quote(string[, delimiter=NULL]):string : 返回字符串 string 的正则表达式。注意:默认不会转义 /,需指定第二个参数为 / 才可以被转义。

感谢你看到了这里。如果文章有错误,请评论指正,谢谢!

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!