有什么区别?:,?!和?=在正则表达式?

问题描述 投票:76回答:4

我搜索了这些表达式的含义,但无法理解它们之间的确切区别。这就是他们所说的:

  • ?:匹配表达式但不捕获它。
  • ?=匹配后缀但将其从捕获中排除。
  • ?!匹配if后缀不存在。

我尝试在简单的RegEx中使用它们,并获得了类似的结果。示例:以下3个表达式给出非常相似的结果。

  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?!\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?=\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9]+)*
javascript regex
4个回答
99
投票

?=?!之间的区别在于前者要求给定的表达式匹配,后者要求它不匹配。例如,a(?=b)将匹配“ab”中的“a”,但不匹配“ac”中的“a”。 a(?!b)将匹配“ac”中的“a”,而不匹配“ab”中的“a”。

?:?=之间的区别在于?=从整场比赛中排除了表达,而?:则没有创建一个捕获组。因此,例如a(?:b)将匹配“abc”中的“ab”,而a(?=b)将仅匹配“abc”中的“a”。 a(b)将匹配“abc”中的“ab”并创建包含“b”的捕获。


61
投票
?:  is for non capturing group
?=  is for positive look ahead
?!  is for negative look ahead
?<= is for positive look behind
?<! is for negative look behind

请在这里查看:http://www.regular-expressions.info/lookaround.html非常好的教程和正则表达式中的前瞻示例。


12
投票

为了更好地理解,让我们应用三个表达式和一个捕获组并分析每个行为。

  • ()捕获组 - 括号内的正则表达式必须匹配,匹配创建捕获组
  • (?:)非捕获组 - 括号内的正则表达式必须匹配,但不能创建捕获组
  • (?=)积极向前看 - 断言正则表达式必须匹配
  • (?!)负向前看 - 断言不可能匹配正则表达式

让我们应用q(u)i退出。 q匹配q和捕获组u匹配你。获取捕获组内的匹配并创建捕获组。因此引擎继续使用i。而i将匹配我。最后一次匹配尝试成功。 qui匹配,创建了一个u的捕获组。

让我们应用q(?:u)i退出。再次,q匹配q和非捕获组u匹配你。将执行与非捕获组的匹配,但不会创建捕获组。因此引擎继续使用i。而i将匹配我。最后一次匹配尝试成功。 qui匹配

让我们应用q(?=u)i退出。前瞻是积极的,后面是另一个令牌。再次,q匹配q和u匹配你。同样,必须放弃前瞻的匹配,因此引擎从字符串中的i退回到u。前瞻是成功的,因此发动机继续使用i。但是i无法与你相提并论。所以这场比赛尝试失败了。

让我们应用q(?=u)u退出。前瞻是积极的,后面是另一个令牌。再次,q匹配q和u匹配你。必须丢弃前瞻的匹配,因此引擎会从字符串中的u退回到u。前瞻是成功的,因此发动机继续使用u。和u匹配你。所以这次比赛尝试是成功的。 qu匹配

让我们应用q(?!i)u退出。即使在这种情况下,前瞻是积极的(因为i不匹配),然后是另一个令牌。再次,q匹配q和i不匹配你。必须丢弃前瞻的匹配,因此引擎会从字符串中的u退回到u。前瞻是成功的,因此发动机继续使用u。和u匹配你。所以这次比赛尝试是成功的。 qu匹配

因此,总而言之,如果您只想测试存在或测试并保存匹配,前瞻和非捕获组之间的真正区别就在于此。捕获组是昂贵的,所以明智地使用它。


5
投票

尝试将foobar与以下内容进行匹配:

/foo(?=b)(.*)/
/foo(?!b)(.*)/

第一个正则表达式将匹配并将返回“bar”作为第一个子匹配 - (?=b)匹配'b',但不消耗它,留下它用于以下括号。

第二个正则表达式不匹配,因为它期望“foo”后跟不同于'b'的东西。

(?:...)与简单的(...)具有完全相同的效果,但它不会将该部分作为子匹配返回。

© www.soinside.com 2019 - 2024. All rights reserved.