介绍正则表达式的基本组成和基本语法。

在线正则检测工具:regexpal

界定符

正则表达式的开始和结束位置,不同语言略有差别,PHP中为"/"或"#"

常见原子/元字符

正则表达式中以Unicode编码表中的字符为原子

Tips:根据此特性,匹配已知汉字时,可以将其转换为Unicode编码进行匹配,以避免编码问题

这里有更详细的列表

.

换行符之外的任意字符

\d

任意一个十进制数字[0-9]

\D

和\d互逆,匹配一个非数字字符。等价于[^0-9]

\s

匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]

\S

和\s互逆,匹配任何可见字符

\w

\w匹配字母或数字或下划线或汉字等

\W

和\w互逆,匹配任何非单词字符。等价于"[^A-Za-z0-9_]"

量词

{n}

前面原子恰好出现n次

{n,}

最少出现n次

{n,m}

最少出现n次,最多出现m次

*

匹配0次、1次、多次其之前的原子{0,}

+

匹配1次、多次{1,}

?

匹配0次、1次{0,1}

Tips:根据区间长度分别为?、+ 、*

边界控制

^

代表字符串的开始

Tips:在[^]情况下为"非"意思

$

代表字符串结尾

模式单元/分组

()

里面为一个整体单元/小组

条件符

|

匹配多个分支选择,为"或"意思

Tips:使用分枝条件时,要注意各个条件的顺序,匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了

[]

匹配里面的任意一个原子

[^]

匹配除里面原子之外的任意字符,^在第一位

修正模式

位于在界定符后,可以多种模式同时存在

U

懒惰匹配,当结果存在歧义时取短
默认贪婪模式,当结果存在歧义时取长

i

忽略英文字符大小写

x

忽略空白

s

让"."匹配包含换行符在内的所有字符

e

仅捕获已被显示命名的分组

分组

(exp)

自动分配组名,同时捕获exp匹配结果

(?<name>exp)/(?'name'exp)

设置分组名,同时捕获exp匹配结果

(?:exp)

不分配组号,不捕获exp匹配结果,只返回是否匹配成功

Tips:默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2。分组0对应整个正则表达式。

断言

(?=exp)

零宽度正预测先行断言,断言自身出现的位置的后面能匹配表达式exp
简单说就是:匹配结果的后面符合exp

//匹配以ing结尾的单词的前面部分(除了ing以外的部分)
$exp = '\b\w+(?=ing\b)';
$str = 'I'm singing while you're dancing';
$result = ['sing','danc'];

(?<=exp)

零宽度正回顾后发断言,断言自身出现的位置的前面能匹配表达式exp
简单说就是:匹配结果的前面符合exp

//以wh开头的单词的后半部分(除了wh以外的部分)
$exp = '(?<=\bwh)\w+\b';
$str = 'I'm singing while you're dancing';
$result = ['ile'];

(?!exp)

零宽度负预测先行断言,断言自身出现的位置的后面不能匹配表达式exp
简单说就是:匹配结果的后面不符合exp

//排除baidu
$exp = '\b((?!baidu)\w)+\b';
$str = 'baidu chengxiaobai';
$result = ['chengxiaobai'];

(?<!exp)

零宽度负回顾后发断言,断言自身出现的位置的前面不能匹配表达式exp
简单说就是:匹配结果的前面不符合exp

//前面不是小写字母的俩位数字
$exp = '(?<![a-z])\d{2}';
$str = 'a12B34';
$result = ['B34'];
//不包含属性的简单HTML标签内里的内容
$exp = '(?<=<(\w+)>).*(?=<\/\1>)';
//(?<=<(\w+)>)指定了这样的前缀:被尖括号括起来的单词
//然后是.*(任意的字符串)
//最后是一个后缀(?=<\/\1>)
//\/是一个/的转义
//\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容.如果(\w+)捕获的是div的话,\1就是div
$str = '<div>chengxiaobai</div>';
$result = ['chengxiaobai'];
Tips:结果并不包含自身。并且后发断言在JS中并不支持,所以目前在线正则测试工具都不能测试后发断言,但在.net、java等后端语言都是支持的

注释

(?#comment)

这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

$exp = '2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)';

参考资料

本作品由 程小白 创作,采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可,可自由转载、引用但需署名作者且注明文章出处。
原文地址:https://www.chengxiaobai.cn/skills/regular-expression-entry.html