首页 > 解决方案 > RegEx:以任意顺序匹配包含唯一组的字符串

问题描述

澄清:我需要这个正则表达式才能在 ECMAScript 中工作。

我想找到一个匹配的正则表达式:

为简单起见,让我们假设(现在)每个组只是一个字符。

然后,对于组大小为 1、2 和 3 的 3 个(唯一)组/字符(这些是任意参数),我们希望匹配:

以下内容不应匹配

有关更多示例,请参阅此链接:https ://regex101.com/r/zpNLHw/2

尝试的解决方案

  1. 使用正前瞻和负前瞻来强制组是唯一的(首先,捕获第一组,然后在捕获第二组时,在之前插入负前瞻以确保第二组与第一组不同,等等。 )。

  2. 在前瞻之后,只需附加^.{total_number_of_characters}$(在本例中为3 + 2 + 1 = 6)。

产生的正则表达式:

(?=.*(.).*\1.*\1)(?=.*(?!\1)(.).*\2)(?=.*(?!\1|\2)(.))^.{6}$

这个尝试的解决方案似乎部分起作用 - 它没有给出错误匹配,但只给出了所需匹配的子集(有关详细信息,请参阅上面的链接)。

正确匹配:

错过的比赛(应该匹配但不匹配):

标签: regex

解决方案


逻辑是你需要先在这里检查更长的模式。原因是,一旦前瞻是原子的(至少,在您使用的正则表达式风格中),并且一旦找到匹配项,当正则表达式引擎尝试回溯时,它们就永远不会重新输入/重新评估。

如果以aaadcc输入为例,您将很容易看到会发生什么。该^(?=.*(.).*\1.*\1)(?=.*(?!\1)(.))(?=.*(?!\1|\2)(.).*\3).{6}$模式首先检查 3 个相同的字符,然后检查与 Grpup 1 中捕获的字符不相等的单个字符,然后搜索除第 1 组和第 2 组之外的两个字符。看看:

  • 一旦正则表达式引擎找到三个as 并a保存在第 1 组缓冲区中,就会退出第一个前瞻。
  • 第二个前瞻的工作方式如下:.*匹配整个aaadcc字符串,然后触发负前瞻并通过,但(.)失败(因为有字符串的结尾)。因此,引擎回溯,并将字符(.)匹配并捕获到第 2 组。c
  • (?=.*(?!\1|\2)(.).*\3)现在搜索不等于aandc并且至少重复两次的字符 - 但d字符串中只有一个。由于前瞻是原子的,因此不会发生重新评估,并且会发生故障。

注意:如果您使用非原子前瞻(如 PCRE2 中的那些),您将获得预期的结果

^(?*.*(.).*\1.*\1)(?*.*(?!\1)(.))(?*.*(?!\1|\2)(.).*\3).{6}$

推荐阅读