这里写自定义目录标题
1. 正则表达式基础
正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。
在很多文本编辑器里, 正则表达式通常被用来检索、替换那些符合某个模式的文本。
什么时候会用到正则表达式? 数据验证、字符串查找、字符串替换。
2. 正则表达式测试工具
2.1. Web 版本
- https://regex101.com
- http://tool.lu/regex
- regexpal(https://www.regexpal.com/)
- http://regexr.com
2.2. 软件
regexTester
2.3. 中文转换 unicode 编码
http://tool.chinaz.com/tools/unicode.aspx
3. 简单演示正则表达式
<?php
header('content-type:text/html;charset=utf-8');
$subject = 'this is a test';
// $pattern = "#This#";
$pattern = '#This#i'; // 找 'This', 忽略大小写
if (preg_match($pattern, $subject)) {
echo '找到了';
} else {
echo '没找到';
}
4. 正则表达式基础语法
PHP 中的正则表达式由定界符、原子、元字符和模式修正符组成。
4.1. 定界符
定界符可以使用除了数字、字母下划线以外的字符。
分隔符可以使任意非字母数字、非反斜线、非空白字符。
定界符使用特殊符号, 像 ~~
、! !
、##
等。
不要使用 \
当作定界符。
在定界符中书写匹配模式。
如果分隔符需要在模式内进行匹配, 它必须使用反斜线进行转义。
如果分隔符经常出现在模式内, 最好使用其他分隔符进行替换。
4.2. 原子
原子是匹配模式中最基础的组成部分, 每个模式至少包含一个原子。
4.2.1. 普通原子
4.2.1.1. 可见原子
a-z
、A-Z
、0-9
4.2.1.2. 不可见原子
\n
、\r
、\t
、\v
、\f
4.2.2. 特殊字符
$(){[|\.^*+?
4.2.3. 通用字符类
\d
: 任意十进制数字, 等价于[0-9]
\D
: 任意非十进制数字, 等价于[^0-9]
\w
: 任意单词字符, 等价于[a-zA-Z0-9_]
\W
: 任意非单词字符, 等价于[^a-zA-Z0-9_]
\s
: 匹配任意空白字符, 等价于[ \f\n\r\t\v]
\S
: 匹配任意非空白字符, 等价于[^ \f\n\r\t\v]
4.2.4. 自定义原子表作为原子
#[aeiou]#
<?php
header('content-type:text/html;charset=utf-8');
// 测试普通原子
$subject = 'king!this is maizi.1234567890HELLO WORLD';
$pattern = '#king#';
$pattern = '#!#';
$pattern = '#.#'; // 如果不转义的话,就表示匹配所有
$pattern = '#\.#'; // 转义后才能匹配到点
// 匹配非打印字符
$pattern = '#\n#';
// 测试通用匹配
$pattern = '#\d#';
$pattern = '#[3-5]#';
if (preg_match($pattern, $subject, $matches)) {
echo '找到了<br/>';
echo '<pre>';
print_r($matches);
echo '</pre>';
} else {
echo '没找到<br/>';
}
4.3. 元字符
-
*
: 匹配 0 次 1 次或多次其前的原子, 等价于{0,}
-
+
: 匹配一次或多次其前的原子,等价于{1,}
-
?
: 匹配 0 次或 1 次其前的原子,等价于{0,1}
-
.
: 匹配除了换行符以外的任意一个字符 -
|
: 匹配两个或多个分支选择 -
{n}
: 表示其前面的原子恰好出现 n 次 -
{n,}
: 表示其前的原子出现不小于 n 次, 即大于等于 n 次 -
{n,m}
: 表示其前的原子至少出现 n 次, 最多出现 m 次 -
^
或\A
: 匹配输入字符的开始的位置(或在多行模式下行的开头, 即紧随一个换行符之后) -
$
或\Z
: 匹配输入字符串的结束位置(活在多行模式下行的结尾, 即紧随一个换行符之前) -
\b
: 匹配单词的边界,如匹配单词is
,可以这样匹配#\bis\b#
-
\B
: 匹配单词的边界以外的部分。#\Bis\B#
不以is
开始也不以is
结尾。 -
[]
: 匹配方括号中的任意一个原子 -
[^]
: 匹配除了方括号中的原子以外的任意一个字符 -
()
: 匹配其整体为一个原子, 即模式单元。
选择
用圆括号将所有选择项括起来, 相邻的选择项之间用 |
分隔。
但用圆括号会有一个副作用, 是相关的匹配会被缓存, 此时可用 ?:
放在第一个选项前来消除这种副作用。
其中 ?:
是非捕获元之一, 还有两个非捕获元是 ?=
和 ?!
, 这两个还有更多的含义, 前者为正向预查, 在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串, 后者为负向预查, 在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
4.3.1. 反向引用
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中, 所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储
缓冲区编号从 1 开始, 最多可存储 99 个捕获的子表达式
每个缓冲区都可以使用 ‘\n’ 访问, 其中 n 为一个标识特定缓冲区的一位或两位十进制数。
可以使用非捕获元字符 ‘?:’、‘?=’ 或 ‘?!’ 来重写捕获, 忽略对相关匹配的保存
4.3.2. PHP 的通用字符簇
字符簇 | 描述 |
---|---|
[[:alpha:]] | 任何字母 |
[[:digit:]] | 任何数字 |
[[:alnum:]] | 任何字母和数字 |
[[:space:]] | 任何空白字符 |
[[:upper:]] | 任何大写字母 |
[[:lower:]] | 任何小写字母 |
[[:punct:]] | 任何标点符号 |
[[:xdigit:]] | 任何 16 进制的数字, 相当于 [0-9a-fA-F] |
4.4. 模式修饰符
i
: 忽略大小写m
: 多行模式, 将字符串视为多行。默认的正则开始 “^” 和结束 “$” 将目标字符串作为单一的一"行"字符。加上 m 后, 那么开始和结束将会指字符串的每一行s
: 模式中的点号元字符匹配所有字符, 包含换行符。如果没有这个修饰符, 点号不匹配换行符x
: 将模式中的空白忽略U
: 非贪婪, 即懒惰匹配D
: 模式中的$
仅匹配目标字符串的结尾。没有此选项时, 如果最后一个字符是换行符的话,$
也会匹配此字符之前。如果设定了 m 修正符则忽略此选项e
: 只用在preg_replace()
函数中, 在替换字符串中对逆向引用做正常的替换, 将其作为 PHP 代码求值, 并用其结果来替换所搜索的字符串u
: 此修正符打开一个与 perl 不兼容的附加功能。模式字符串被认为是 utf-8 的.
5. 正则表达式优化
- 使用字符组代替分支条件
- 优先选择最左端的匹配结果
- 标准量词是匹配优先的
- 谨慎用点号,尽可能不用
*
和+
这样的任意量词 - 能用字符串函数处理的就尽量使用字符串函数处理
- 合理使用括号
- 能确定起始和结束位置尽量使用
^
和$
- 可以对比较大的正则表达式进行拆分匹配