专栏首页dylanliu正则表达式-锚点及模式修饰符

正则表达式-锚点及模式修饰符

上一篇入门介绍了匹配单个字符的元字符和计数元字符,最后的练习里我们使用了括号,这也是正则里的元字符之一,是用来限定匹配子结构和捕获用的,有些不太好分类但是我们常用的控制结构,我们将他们放到其他元字符中。

其他元字符

来看我们常用的一些:

元字符

名称

含义

|

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

文字文本范围

之间的字符全部当做文本,不解析为元字符

  • 在Java中可以在编译Pattern时指定不区分大小写,grep也可以使用-i来启用,但这是针对正则表达式全局的设定,如果我们要对局部进行细微控制的话,就需要用到(?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),域名可以把想到的都写进去。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 正则表达式-基本概念与简单元字符

    首先,正则表达式是一个字符串组成的模式,用来匹配一个字符串,一般用在检索,替换里,也经常用来校验一些字符模式,检验是否匹配一个给定的规则。

    Dylan Liu
  • 正则表达式-引擎

    现在基本所有的文字编辑软件都会包含正则表达式的功能,但是不同的编辑器所使用的引擎实现原理是不一样的,现在大家用的有三种引擎:

    Dylan Liu
  • 正则表达式-分隔符示例

    文本中经常需要匹配分隔符内的内容,像程序中的注释以/*开头,*/结尾;双引号""内的字符等,我们今天以这个例子来一步步的构建这个正则表达式

    Dylan Liu
  • 写给前端的正则表达式入门

    在 JavaScript 中,使用 // 即可创建一个正则表达式对象,当然也可以使用 new RegExp()

    savokiss
  • 匈牙利算法

    二分图:又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边所关联的两个顶点i...

    五分钟学算法
  • 正则表达式详解

    点号(.)是元字符,匹配除换行符以外的任意字符。 星号(*)是元字符,代表数量。 点号星号连在一起就是匹配任意数量的不包括换行符的字符。 \s匹配任意空白字符。...

    wangxl
  • 全网最易懂的正则表达式教程(5)- 断言

    和单词的边界类似,在正则中还有文本每行的开始和结束,如果要求匹配的内容要出现在一行文本开头或结尾,就可以使用 ^ 和 $ 来进行位置界定

    小菠萝测试笔记
  • 全网最易懂的正则表达式教程(2)- 特殊单字符和空白符

    https://www.cnblogs.com/poloyy/category/1796055.html

    小菠萝测试笔记
  • 【1】python-正则表达式语法规范与

    【说明】:该文主要为了随后复习和使用备查,由于做了word文档笔记,所以此处博文没有怎么排版,没放代码,以插入图片为主,

    py3study
  • 全网最易懂的正则表达式教程(3)- 量词

    记住,限定符只对它前面一个元字符生效,这里是 1 ,所以是匹配一个 1 或者多个 1

    小菠萝测试笔记

扫码关注云+社区

领取腾讯云代金券