前言
最近在系统的学习 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
: 搜索string
与pattern
给定的正则表达式的一个匹配。如果提供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
的正则表达式。注意:默认不会转义/
,需指定第二个参数为/
才可以被转义。
感谢你看到了这里。如果文章有错误,请评论指正,谢谢!