正则表达式

Posted dongye95

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则表达式相关的知识,希望对你有一定的参考价值。

正则表达式

Micbael·Fitzgerald 人民邮电出版社


第 1 章 什么是正则表达式

正则表达式有助于找到文本字符串中的各种模式。更确切地说,正则表达式是经过专门编写的文本字符串,用来匹配字符串(尤其是文件内字符串)集合中符合该模式的所有字符串。

正则表达式是描述一组字符串特征的模式,用来匹配特定的字符串。

707-827-7019这种正则表达式是用 字符串字面值 (string literal) 来匹配目标字符串的。

字符串字面值: 字面上看起来是什么就是什么。

正则表达式将方括号视为特殊的 元字符(metacharacter),因此方括号不参与匹配。

元字符: 在正则表达式中有特殊含义的字符,也是保留字符。

[0-9]这种形式的正则表达式称做 字符组(charactercla ss),有时也叫 字符集(characterset)

可以对数字的范围进行进一步限定。用更具体的一组数字也能得到同样的结果,比如[12789],这个字符组只会匹配列出的数字,即1、2、7、8、9。d可以匹配任意阿拉伯数字。

这种正则表达式叫做 字符组简写式(character shorthand),也叫 转移字符(character escape)

可以使用以下表达式来匹配电话号码中的任意数字:ddd-ddd-dddd除了和上面表达式一样,使用连字符本身(-)来匹配连字符之外,也可以用转义的大写D(D)。它匹配任何一个非数字字符。dddDdddDdddd

还可以用点号(.)来匹配连字符ddd.ddd.dddd点号(英文句号)是一个通配符,可以匹配任意字符(但某些情况下不能匹配行起始符)。它也可以匹配百分号(%)或竖线(|)ddd%ddd%ddddddd|ddd|dddd

本节我们使用捕获分组(capturing group)来匹配电话号码中的某一部分。然后使用后向引用(backreference)对分组中的内容进行引用。要创建捕获分组,先将一个d放在一对圆括号中,这样就将它放入了一个分组中,后面可以用1来对捕获的内容进行后向引用:(d)d11对括号内分组捕获的内容进行了反向引用。这个正则表达式匹配的是区号707。

  • (d)匹配第一个数字并将其捕获(数字7)

  • d匹配第二个数字(数字0)但没有捕获,因为没有括号

  • 1对捕获的数字进行反向引用(数字7)

707-827-7019(d)01Ddd1D1dddd{3}-?d{3}-?d{4}花括号中的数字表示待查找的数字出现的次数。包含数字的花括号是一种量词(quantifier)。花括号本身用做元字符。

问号是另一种量词,在以上表达式中表示连字符是可选的。也就是说,连字符可以不出现或只出现一次。还有其他的量词,例如加号(+)表示“一个或多个”,星号(*)表示“零个或多个”使用量词能让正则表达式变得更简洁:

(d{3,4}[.-]?)+

  • 左圆括号 ( 为捕获分组的起始符

  • 反斜杠 为字符组简写式的起始符(对之后的字符进行转义)

  • 字符d为字符组简写式的结束符(d匹配0到9范围内的任意数字),

  • 左花括号 { 为量词起始符;

  • 数字3为匹配的最小数量;

  • 逗号 , 隔开不同的数量;

  • 数字4为匹配的最大数量;

  • 右花括号 } 为量词的结束符;

  • 左方括号 [ 为字符组的起始符;

  • 点号 . (匹配点号本身);

  • 连字符 - 匹配连字符的本身;

  • 右方括号 ] 为字符组的结束符;

  • 问号 ? 表示量词“零个或一个“;

  • 右圆括号 ) 为捕获分组的结束符;

  • 加号 + 表示量词“一个或多个“。

这个表达式能用但不完全对,因为它只能匹配3位或4位的数字,而不管是否符合电话号码的格式。改进:(d{3}[.-]?){2}d{4}这个表达式匹配的字符串是连续两个无括号的三位数字,每三位数字后可以带连字符也可以不带,最后是一个四位数字。

括选文字符最后这个正则表达式表示第一个3位数字可以带也可以不带括号,即区号是可选的:

^((d{3})|^d{3}[.-]?)?d{3}[.-]?d{4}$

  • 出现在正则表达式起始位置或者竖线(|)之后的脱字符^,表示电话号码会出现在一行的起始位置;

  • 左括号 ( 为捕获分组的起始符;

  • (表示左括号本身;

  • d匹配一位数字,

  • d之后的{3}是量词,表示匹配三位数字;

  • )匹配右括号本身;

  • 竖线符|表示选择,也就是从多个可选项中选择一个,换句话说,它表示“匹配一个不带括号的区号或一个带括号的区号“;

  • 脱字符 ^ 匹配行起始位置;

  • d匹配一位数字,

  • {3}是表示匹配三位数字的量词;

  • [.-]? 匹配一个可选的点号或连字符;

  • 右括号 ) 为捕获分组的结束符,

  • 问号 ? 表示分组可选,即分组中的前缓可有可无;

  • d匹配一位数字;

  • {3}表示匹配三位数字的量词;

  • [.-]?匹配另一个可选的点号或连字符;

  • d匹配一位数字;

  • {4}是表示匹配四位数字的量词:

  • 美元符$匹配行结束位置。

这个表达式最终匹配十位的北美电话号码,而且括号、连字符或者点号都是可选的。

以上正则表达式中的捕获分组并不是必需的。分组是必要的,但是捕获不需要,更好的方法是使用非捕获分组。(之后才讨论)

为什么有那么多编写正则表达式的方法?一个原因是正则表达式具有可组合性(composability)。

第 2 章 简单的模式匹配

正则表达式唯一的用途就是在文本中匹配和寻找模式,模式可以简单也可以复杂。

2.1 匹配字符串字面值

正则表达式最为直接和明显的功能就是用一个或多个字符字面值来匹配字符串。

2.2 匹配数字

d 和 [0-9]效果是一样的字符组[0-9]表示范围,这意味着它会匹配0至9范围内的数字。数字的字符组简写式d更为简短,但却没有字符组强大、灵活。在无法使用d时(不是所有情况下都支持这种方式),或者想匹配特定数字时,就需要使用字符组,合适的时候可以使用d,因为它更简短。

2.3 匹配非数字字符

通常可以将简写式取反,取反的结果就是排除。比如,要匹配非数字字符,可使用包含以下大写字母D的简写式:D[^0-9][^d]

2.4 匹配单词和非单词字符

wD与w的区别是D会匹配空格、标点符号(引号、连字符、反斜杠、方括号)等字符,而w却不会,它只匹配字母、数字和下划线。在英语环境中,与w匹配相同内容的字符组为:[_a-zA-Z0-9]现在用大写字母W匹配非单词字符:W相当于[^_a-zA-Z0-9]

字符简写式描述
a 报警符
[] 退格字符
c x 控制字符
d 数字字符
D 非数字字符
o xxx 字符的八进制
w 单词字符
W 非单词字符
空字符
x xx 字符的十六进制值
u xxx 字符的Unicode值

2.5 匹配空字符

s以下字符组与s匹配的内容相同:[ ]也就是,它会匹配:

  • 空格

  • 制表符( )

  • 换行符( )

  • 回车符( )

要匹配非空白字符:S这个简写式匹配除空白符之外的所有符号。它匹配字符组:[^ ]或者[^s]

匹配各种空白符的简写式

字符简写式描述
f 换页符
h 水平空白符
H 非水平空白符
换行符
回车符
s 空白符
S 非空白符
水平制表符
v 垂直制表符
V 非垂直制表符

2.6 再谈匹配任意字符

用正则表达式匹配任意字符的一种方法就是使用点号(U+002E)。点号可以匹配除行结束符之外的所有字符,个别情况除外。要匹配 THE RIME 整个短语,则可使用八个点号:........但这种方法太麻烦,所以推荐用量词:.{8}这个表达式能匹配前两个单词以及它们之间的空格,但只是粗略的匹配。(所有字符都可匹配到)

下面是匹配单词的边界和字母的开始和结束位置。A.{5}T这个表达式有更强的特指性(specificity),它匹配单词ANCYENT,也就是ancient的旧式拼写形式。

  • 简写式  匹配单词边界,不消耗任何字符

  • 字符 A 和 T 限定了字符序列的首尾字母

  • .{5}匹配任意五个字符

  • 简写式  匹配单词的另一个边界

w{7}.*它就相当于[^ ][^ ]类似的,点号也可以与表示“一个或多个”的量词(+)连用:.+这涉及到量词的贪心特性。所谓 “贪心”(greedy),指量词会匹配所有能匹配的字符。

2.7 给文本加标签

怎么让“The Rime of the Ancient Mariner”的内容以网页而不是纯文本形式显示呢?换句话说,怎么使用正则表达式而不是手写方式为它们添加html5标签呢?

点击RegExr中的Replace(替换)标签,选中multiline(多行)选项,然后在第一个文本框中键入:(^T.*$)这个表达式会从文件的开始匹配诗文的第一行,然后使用括号将文本捕获到一个分组中。在第二个文本框中键入:<h1>$1<h1>这个替换表达式将 $1 捕获的内容嵌套在了 h1 标签中。可以在底部的文本框中看到结果。$1 是一个 Perl 风格的后向引用。此外,在包括Perl在内的多数实现程序中,还可以使用 1 表示后向引用,但是RegExr只支持 $1、$2、$3 这样的方式。

2.7.1 用sed为本文加标签

echo Hello | sed s/Hello/Goodbye

  • echo命令将在标准输出设备(通常是屏幕)中打印单词Hello,竖线符(|)将打印内容通过管道传到之后的sed命令

  • 管道将echo的输出转为sed的输入

  • sed的s命令将单词Hello变为Goodbye,而Goodbye就显示在屏幕上了。

sed -n ‘s/^/<h1>/;s/$/</h1>/p;q‘rime.txt输出:<h1>THE RIME OF THE ANCYENT MARINERE,IN SEVEN PARTS.</h1>

  • 首先调用sed程序

  • sed默认的操作是直接复制每行输入并输出,-n选项覆盖了该默认操作。之所以要覆盖默认操作,是因为我们只想让正则表达式影响第1行。

  • s/^/<h1> 在行的开头(^)添加 <h1> 标签

  • 分号(;)用于分隔命令

  • s/$/</h1>/ 在行的结尾($)添加</h1>标签

  • 命令p会打印受影响的那一行(第1行)。与-n不同,后者会打印所有行。

  • 最后命令q会结束程序,这样sed程序就只会处理第1行。

  • 所有的操作都是针对rime.txt文件执行的

这行命令还有另一种写法,即用-e选项分别引导每个命令。

sed -ne ‘s/^/<h1>/‘ -e ‘s/$/</h1>/p‘ -e ‘q‘ rime.txt可以将这些命令写到文件里,比如这里所示的文件h1.sed(该文件就在之前所说的代码库里)

#!/usr/bin/sed
?
s/^/<h1>/
s/$/</h1>/
q

若要运行该文件,请在与rime.txt同一个路径或文件夹里运行如下命令:


sed -f h1.sed rime.txt

2.7.2 用Perl为文本加标签

Perl以正则表达式的强大支持和文本处理能力而闻名。在命令提示符中键入:


perl -ne ‘if ($. == 1) { s/^/<h1>/; s/$/</h1>/m; print; }‘ rime.txt

结果和sed一样:<h1>THE RIME OF THE ANCYENT MARINERE,IN SEVEN PARTS.</h1>

以下是这个Perl命令的执行过程解析。

  • perl调用了perl程序

  • -n选项输出全部输入内容(rime.txt文件)

  • -e选项允许在命令行(而不用在文件)中提交程序代码

  • if语句检查是否在第一行。在Perl中 $.是个特殊的变量,它匹配当前行。

  • 第一个替换命令 s 先找到第一行的开头(^)然后插入 <h1> 标签

  • 第二个替换命令s搜寻行结尾 ($)再插入 </h1> 标签。

  • 替换命令最后的 m(多行)修饰符,表示将本行单独处理;这样, $就只匹配第一行的结尾而不会匹配整个文本的结尾。

  • 最后在标准输出设备(屏幕)中打印出结果。

  • 所有这些操作都是针对rime.txt的。

同样可以将这些命令放入程序文件中,比如示例代码库中的h1.pl文件。


#!/usr/bin/perl -n
?
if ($. == 1){
s/^/<h1>/;
s/$/</h1>/m;
print;
}

然后在rime.txt的同一个目录下,执行如下命令:perl h1.pl rime.txt

第 3 章 边界

本章的重点是断言。断言是标记边界,但是并不耗用字符。也就是说,字符并不会返回到结果中。断言也被称做 “零宽度断言(zero-width assertion)”。零宽度断言不匹配字符,而是匹配字符串中的位置。其中的一些,比如 ^和$,也叫做 锚位符(anchor)边界有以下几种:

  • 行或者字符串的起始与结束位置

  • 单词边界(两种)

  • 主题词的起始与结束位置

  • 引用字符串字面值的边界

3.1 行的起始与结束

就像之前看到的那样,要匹配行或字符串的起始要使用脱字符(U+005E):^根据上下文,^会匹配行或者字符串的起始位置,有时还会匹配整个文档的起始位置。而上下文则依赖于应用程序和在应用程序中所使用的选项。如你所知,若要匹配行或字符串的结尾位置要使用美元符:$

^How.*Country.$它会匹配以单词How开头的整行。请注意结尾的点号之前有一个反斜杠,它对点号进行转移,这样点号就被解释为字面值。如果不对点号转义,它就会匹配任意字符。如果要匹配作为字面值的点号,则必须将点号转义或者将其放入字符组中。

3.2 单词边界与非单词边界

 匹配单词边界THE就像 ^ 和 $一样, 是个零宽度断言,表面上它会匹配空格或者是行起始,而实际上它匹配的是个零宽度的不存在的东西。要匹配一个非单词边界。可以:BeB会匹配到小写字母e,而匹配的字母e的两边都是其他字母或者是非单词字符。零宽度断言不会匹配两边的字符,但它会识别文字e的两边是否是非单词边界。

在有些应用程序中,指定单词边界的另一种方法是使用:<来指定单词的开头,而使用>

来指定单词结尾。这是比较旧的语法,在很多最新的正则表达式应用程序中无法使用。但在有些情况下,这种语法就很有用,因为它不会像  那样匹配任意单词边界,而是允许你分别匹配单词的开头或结尾。


grep -Eoc ‘<(THE|The|the)>‘ rime.txt

-E选项表示要使用扩展的正则表达式(ERE),而不是grep的默认使用的基本正则表达式(BRE)。-o选项代表结果只显示一行中与模式相匹配的那部分。-c选项的意思是只返回结果的数量。但引号中的模式会对THE/The或者the进行整词匹配。这就是<>帮你寻找的。返回259


grep -Eoc ‘(THE|The|the)‘ rime.txt

会返回327

3.3 其他锚位符

与锚位符 ^ 相似,以下简写式匹配主题词的起始:A这个写法不是在所有的正则表达式程序中都可以使用的,但可以在Perl和PCRE中使用。要匹配主题词的结尾,可以使用:在某些上下文中还可用:z

3.4使用元字符的字面值

可以用QE之间的字符集匹配字符串字面值。

.^$*+?|(){}[]-

这15个元字符在正则表达式中有特殊含义,用来编写匹配模式。(连字符在字符组的方括号中用来表示范围。但在其他情况下,则无特殊含义)Q$E它将匹配 $,因为 Q 和 E 之间的任意字符都会被解释为普通字符。(记住,可以在元字符之前加一个使其匹配字面值)

3.5 添加标签

略略略

第 4 章 选择、分组和后向引用

4.1 选择操作

选择操作可在多个可选模式中匹配一个。(the|The|THE)可以使用一个选项来使分组更简短。借助选项,可以指定查找模式的方法。(?i)让你的模式不再区分大小写。因此原来带选择操作的模式可以简写成:(?i)the

选项描述支持平台
(?d) Unix中的行 Java
(?i) 不区分大小写 PCRE、Perl、Java
(?J) 允许重复的名字 PCRE
(?m) 多行 PCRE、Perl、Java
(?s) 单行(dotall) PCRE、Perl、Java
(?u) Unicode Java
(?U) 默认最短匹配 PCRE
(?x) 忽略空格和注释 PCRE、Perl、Java
(?-‘‘‘) 复原或关闭选项 PCRE

4.2 子模式

多数情况下,提到正则表达式中的子模式(subpattern),就是指分组中的一个或多个分组。子模式就是模式中的模式。多数情况下,子模式中的条件能得到匹配的前提是前面的模式得到匹配,但也有例外。子模式的写法可以有很多种,这里我们主要关注括号中的子模式。

(the|The|THE)有三个子模式。但是这种情况下,匹配第二个子模式不依赖于是否匹配第一个。(最左边的模式会首先匹配。)以下模式中,子模式依赖于前面的模式:(t|T)h(e|eir)通俗地讲,这个模式会匹配字面值t或T,然后是一个h,接下来就是一个e或者是eir。相应地,这个模式会匹配以下所有情况:

  • the

  • The

  • their

  • Their

以上情况中,第二个子模式(e|eir)依赖于第一个子模式(tT)。括号对于子模式不是必需的。[tT]h[ceinry]*这个模式会匹配the或The还有thee,thy以及thence等单词。两个单词边界()表示该模式只匹配整个单词,而不会匹配单词中的某几个字母。

  • 匹配单词起始边界

  • [tT]是字符组,它匹配小写字母t或者大写字母T。可以将其看作是第一个子模式。

  • 然后匹配(或尝试匹配)小写字母h

  • 第二个也就是最后一个子模式也表示为字符组[ceinry],其后用量词*表示零个或多个。

  • 最后,该模式以另外一个结束

4.3 捕获分组和向后引用

当一个模式的全部或者部分内容由一对括号分组时,它就对内容进行捕获并临时存储于内存中。可以通过后向引用重用捕获的内容,形式为:1$1这里 1$1 引用的是第一个捕获的分组,而2或$2引用第二个捕获的分组,以此类推。sed只接受1这种形式,而Perl则两种都接受。

4.4 非捕获分组

还有一种分组是非捕获分组(Non-Capturing Group)。非捕获分组不会将其内容存储在内存中。在你并不想引用分组的时候,可以使用它。由于不存储内容,非捕获分组就会带来较高的性能,而运行本书的简单示例很难察觉到性能的提升。(?:the|The|THE)或者可以这样做:(?:(?i)the)不过,下面这种写法最值得推荐:(?i:the)该选项i可以放在问好和冒号之间

原子分组

另一种非捕获分组时原子分组(atomic group)。如果你使用的正则表达式引擎进行回溯操作,这种分组就可以将回溯操作关闭,但它只针对原子分组内的部分,而不针对整个正则表达式。(?>the)正则表达式处理过程缓慢的一个因素就是回溯操作。其原因就是回溯操作会尝试每一种可能性,这会消耗时间和计算资源。有时它会占用大量时间。回溯有可能产生巨大的负面效应,这被称为灾难性回溯。原子分组可以关闭正则表达式的部分回溯操作。

第 5 章 字符组

字符组有时也被称为方括号表达式(bracketed expression)。字符组有助于匹配特定字符或者特定的字符序列。它们可以像字符简写式那样代表一大批字符。比如,d匹配的字符与[0-9]所匹配的字符一样。但字符组更有针对性,因此用途比简写式更广。想匹配10-19的偶数:1同理,也能想到用下面的表达式查找0-99的偶数:[24680]|1-9要想创建一个匹配十六进制数的字符组怎么做:[a-fA-F0-9]还可以在字符组内使用简写式。例如,要匹配空格和单词字符,可以创建这样一个字符组:[ws]它等同于[_a-zA-Z ]

5.1 字符组取反

脱字符(^)的意义就是:不,我不想匹配这些字符。(脱字符必须出现在起始位置)

5.2 并集与差集

字符组可以像集合那样操作。事实上,字符组的另一个名称就是字符集(character set)。(并不是所有的实现程序都支持这项功能)[0-3[6-9]]匹配差集(实质上就是减操作):[a-z&&m-r]这匹配a到z之间的字符,但其中m到r之间的字符除外。

第 6 章 匹配Unicode和其他字符

略略略

第 7 章 量词

7.1 贪心、懒惰和占有

贪心: 量词自身是贪心的。贪心的量词会首先匹配整个字符串。尝试匹配时,它会选定尽可能多的内容,也就是整个输入。量词首次尝试匹配整个字符串,如果失败则回退一个字符后再次尝试。这个过程叫做回溯(backtracking)。它会每次回退一个字符,直到找到匹配的内容或者没有字符可尝试为止。此外,它还记录所有的行为,因此相较另两种方式它对资源的消耗最大。

懒惰: (有时也说勉强)。它从目标的起始位置开始尝试寻找匹配,每次检查字符串的一个字符,寻找它要匹配的内容。最后,它会尝试匹配整个字符串。要使一个量词成为懒惰的,必须在普通量词后添加一个问号(?)。它每次只“吃”一点。

占有量词: 会覆盖整个目标然后尝试寻找匹配内容,但它只尝试一次,不会回溯,占有量词就是在普通量词之后添加一个加号(+)。它不“咀嚼”而是直接“吞咽”,然后才想知道“吃”的是什么。

7.2 用*、+和?进行匹配

.* 它将会以贪心的方式匹配主文本中的所有字符。(数字)。要匹配一个或多个9,尝试:9++会寻找至少一个9,而*会寻找零个或多个9.要匹配零次或一次,可使用:9?

7.3 匹配特定次数

使用花括号可以限制某个模式在某个范围内匹配的次数,未经修饰的量词就是贪心量词。7{1}会匹配第一个出现的7.要匹配一个或多个数字7,只要加一个逗号即可:7{1,}

7+和7{1,}本质上是一样的。7*和7{0,}也是相同的。

换可以匹配m到n次7{3,5}

语法描述
{n} 精确匹配n次
{n,} 匹配n次或更多次
{m,n} 匹配m至n次
{0,1} 与?相同(零次或一次)
{1,} 与+相同(一次或更多)
{0,} 与*相同(零次或更多)

7.4 懒惰量词

懒惰的基本特性就是匹配尽可能少的字符——包括0次。5*?不会匹配任何内容,因为可以选择匹配最少的次数——0次。5+?最少匹配一个,所以它匹配一个。5{2,5}?只匹配了两个5,而不像贪心量词那样匹配5个。

语法描述
?? 懒惰匹配零次或一次(可选)
+? 懒惰匹配一次或多次
*? 懒惰匹配零次或多次
{n}? 懒惰匹配n次
{n,}? 懒惰匹配n次或多次
{m,n}? 懒惰匹配m至n次

7.5 占有量词

占有式匹配很像贪心式匹配,它会选定尽可能多的内容。但与贪心式匹配不同的是它不进行回溯。它不会放弃所找到的内容,它很自私,这也是把它称为占有式(possessive)的原因。它仅仅“抱”住自己所选的内容,一点也不放弃。但占有量词的优点是速度快,因为无需回溯。当然,匹配失败的话也很快。

先尝试匹配以零开头的多个零,然后再匹配以零结尾的多个零。0.*+所有的零都被标亮了。存在一个匹配。占有式的匹配看起来和贪心式的匹配是一样的,但没有回溯。

.*+0没有匹配——原因就是没有回溯。它一下就选定了所有的输入,不再回过来查看。如果将加号去掉,它会找到所有的0,因为它变回贪心式匹配了。.*0当知道文本中的内容时,就知道在哪里可以找到匹配,这时应该使用占有量词。不在乎它是否会选定所有内容。占有式匹配有助于提高匹配的性能。

语法描述
?+ 占有式匹配零次或一次(可选)
++ 占有式匹配一次或多次
*+ 占有式匹配零次或多次
{n}+ 占有式匹配n次
{n,}+ 占有式匹配n次或更多次
{m,n}+ 占有式匹配m至n次

环视

环视是一种非捕获分组,它根据某个模式之前或之后的内容匹配其他模式。环视也称为 零宽度断言。

环视包括:

  • 正前瞻

  • 反前瞻

  • 正后顾

  • 反后顾

8.1 正前瞻

假设要匹配单词ancyent,且要求紧随其后的单词是marinere。(?i)ancyent (?=marinere)由于我们使用了不区分大小写的选项(?i),就不必担心模式中用的大小写形式了。现在就是在每一行中寻找后跟marinere的单词ancyent。只有模式的第一部分(ancyent)被标亮,(marinere)不会标亮。

8.2 反前瞻

反前瞻是对正前瞻的取反操作。这意味着要匹配某个模式时,需要在它后面找不到含有给定前瞻模式的内容。(?i)ancynet (?!marinere)

只有一个字符发生了变化:正前瞻的等号(=)变为反前瞻的感叹号(!)。

8.3 正后顾

(?i)(?<=ancyent) marinere

正后顾使用小于号(<),提醒你后顾是哪个方向。被标亮的是marinere而不是ancyent。

8.4 反后顾

反后顾会查看某个模式在从左至右的文本流的后面没有出现。同样,它有一个小于号(<),提醒后顾的是哪个方向。(?1)(?<!ancyent) marinere

^(?(?:d{3}))?[-.]?(?:d{3})[-.]?(?:d{4})$

  • ^是判断一行或者主题词开头的零宽度断言

  • (?是一个字面左括号,但它是可选的(?)

  • (?:d{3})是一个匹配连续三位数字的非捕获分组

  • )?是可选的右括号

  • [-.]?允许有可选的连字符或者句点(点号)

  • (?:d{3})是另一个匹配连续三位数字的非捕获分组

  • (-.)?再次允许有可选的连字符或者句号(点号)

  • (?:d{4})是匹配连续四位数字的非捕获分组

  • $匹配一行或主题词的结尾

匹配电子邮件地址的正则表达式:^({w-.!#$%&‘*+-/=?^_{|}~]+)@((?:w+.)+)(?:[a-zA-Z]{2,4})$`

 

以上是关于正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

markdown 正则表达式模式片段

正则表达式匹配特定的 URL 片段而不是所有其他 URL 可能性

循环通过 python 正则表达式匹配

asp.net 使用正则表达式验证包含打开/关闭括号片段的属性字符串

攻破难啃的骨头-正则表达式(转)

正则表达式的贪婪和非贪婪模式