上一篇入门介绍了匹配单个字符的元字符和计数元字符,最后的练习里我们使用了括号,这也是正则里的元字符之一,是用来限定匹配子结构和捕获用的,有些不太好分类但是我们常用的控制结构,我们将他们放到其他元字符中。
来看我们常用的一些:
元字符 | 名称 | 含义 |
---|---|---|
| | alternation | 匹配分隔的表达式 |
() | 括号 | 限定结构的范围,分组,捕获计数 |
(?:……) | 限定范围和分组,但不增加捕获计数 | |
\1,\2 | 反向引用 | 匹配之前第一、第二括号内表达式匹配的内容 |
(?<Name>) | 命名捕获 | 可以使用名称来获取分组内容group(Name),而不是group(1)方式 |
(?> ) | 固化分组 | 不会交还已经匹配的内容 |
(?(if-exp) then-exp | else-exp) | 条件判断 |
[1-5]
,跟1|2|3|4|5
在语义上是等价的,不过我们在实现的时候能用字符组还是用字符组,因为多选结构正则引擎在没有优化的情况是会一个个匹配然后回溯的,效率上不如字符组
\1
\2
等方式来反向引用前面分组正则匹配到的内容。举个例子,想找到连续两个重复单词,我们就必须要知道前面单词是什么,这时候就可以使用反向引用了,可以简单写为(\w+)\s+\1
,这里没有界定单词,但在平常我们使用已经够了,后面可以加上单词分界符更精确
(?:)
结构跟括号作用基本一样除了不增加捕获计数,也就是说不能使用反向引用来引用括号里的匹配内容,因为使用带捕获的括号时,正则引擎需要记录括号里的捕获内容,回溯时也需要更改状态,如果只是为了分组,我们就可以使用它来减少引擎负担,加快速度
\1
方式来引用,而是可以直接使用name
引用
讲了其他一些控制字符,我们再来看下匹配位置的元字符,这里需要记住一点:
锚点不会匹配实际的文本,而是寻找特定的位置
也就是说锚点会去查看前后字符是否符合你的要求,但是并不占用字符
元字符 | 名称 | 含义 | 示例与注 |
---|---|---|---|
^ | 脱字符 | 匹配一行开头 | |
\A | 匹配文本的起始位置 | vim里匹配一个单词起始,notepad++匹配到下一个字符,暂未想到用处 | |
$ | 美元符 | 匹配一行结束位置 | |
\Z \z | 匹配文本结束位置 | ||
\< | 单词分界符 | 匹配单词开始 | java中使用\b |
\> | 单词分界符 | 匹配单词结束 | java中使用\B |
(?=……) | 顺序环视 | 匹配右侧文本 | (?=Jeffery)Jeff 位置定在J之前但后面必须是Jeffery |
(?<= ) | 逆序环视 | 匹配左侧文本 | (?=Jeff)ery 位置定在f之后,匹配ery, s/(?<=Jeff)(?=s)/'/g 将Jeffs变为Jef's |
(?!) | 否定顺序环视 | 不匹配右侧文本 | |
(?<!) | 否定逆序环视 | 不匹配左侧文本 |
^$
匹配一行开头与结尾,很常见,不多说\<
与\>
是单词分界符,也有使用\b
与\B
来分界的,在前面匹配重复单词时,我们就可以使用\<(\w+)\>\s*\1
来界定单词,这样this is a test test ha ha
is就不会被认为是重复单词的一个了(?=Jeffery)Jeff
里要求匹配Jeff,但是右侧必须为Jeffery,也就是说只匹配Jeffery里的Jeff,其余的Jeffary等就不能匹配".*?"
来匹配,也可以使用"[^"]*"
来匹配,更可以使用否定顺序环视"((?!").)*"
来匹配模式修饰词 (?modifier)
元字符 | 名称 | 含义 | 示例与注 |
---|---|---|---|
(?i) | 开启不区分大小写匹配 | 应用在子表达式中 | |
(?-i) | 关闭不区分大小写匹配 | 与(?i)配合使用 | |
\Q..\E | 文字文本范围 | 之间的字符全部当做文本,不解析为元字符 |
(?i)
来指定不区分大小写了,譬如想匹配Petter
,首字母不区分大小写,但是后续字母必须全是小写,我们就可以使用(?i)p(?-i)etter
,这样就不会匹配到PETTER
\Q..\E
来限定,里面的字符不会被解析为元字符本节已经把常用的元字符全部都罗列完了,Unicode相关的控制\p
等没有列出,平常用不太多,把这些融汇贯通基本就可以解决90%的正则问题了。接下来我们来探讨一下正则引擎的原理,有助于我们写出正确、效率高的正则表达式。
匹配一个email,自己写一下再与网上的对照一下。
email模式,前面是名称,中间是@符,最后是机构域名
可以简单写为:[-0-9a-zA-Z_]+@\w+(\.\w+)+
这里没有做严格验证,譬如说开头不能是下划线和横线,结尾域名也不能是随意的单词,看大家的使用场景,有时候用这个就够了,有时候需要更精确一点。
加上限制,可以写为[0-9a-zA-Z]+[-0-9a-zA-Z_]*@[0-9a-zA-Z]+\.(com|cn|org|net)
,域名可以把想到的都写进去。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有