RegEx:匹配包含任意顺序的唯一组的字符串



说明:我需要这个正则表达式在ECMAScript中工作

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

  • 出现给定次数(当然至少一次)的唯一组,

为简单起见,我们假设(目前)每个组只有一个字符。

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

  • aaabbc
  • xxxyyz
  • ababac
  • ccbabc

不能匹配:

  • aaaaaa
  • aaabbcc
  • aabbcd

更多示例请参见此链接:https://regex101.com/r/zpNLHw/2

<标题>试图解决方案
  1. 使用正向前看和负向前看相结合来强制组是唯一的(首先,捕获第一个组,然后在捕获第二个组时,插入一个负向前看,以确保第二个组不同于第一个组,等等)。

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

导致的正则表达式:

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

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

正确的匹配:

  • aabccc
  • aabbbc
  • aaabbc

缺少匹配(应该匹配但不匹配):

  • abbccc
  • abbbcc
  • aaabcc

这里的逻辑是您需要首先检查较长的模式。原因是,一旦查找头是原子的(至少,在您使用的regex风格中),并且一旦它们找到匹配,当regex引擎尝试回溯时,它们永远不会被重新输入/重新计算。

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

  • 一旦regex引擎找到三个a并且a保存在Group 1缓冲区中,就退出第一个向前看。
  • 第二次向前看是这样工作的:.*匹配整个aaadcc字符串,然后触发负向前看并通过,但(.)失败(因为有字符串的结束)。因此,引擎回溯,(.)匹配并捕获c字符到组2。
  • (?=.*(?!1|2)(.).*3)现在搜索一个不等于ac的字符,并且至少重复两次-但是字符串中只有一个d不会发生重新求值,因为查找头是原子的,发生故障。

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

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

这只是部分答案——它给出了我们需要的正则表达式,但并没有解释为什么前面的尝试不起作用。

事实证明,指定组的顺序很重要,尽管我真的不明白为什么(如果能解释一下,我将非常感激)。

最初,我们有:

(?=.*(.).*1.*1)(?=.*(?!1)(.))(?=.*(?!1|2)(.).*3)^.{6}$;即按3, 1, 2的顺序指定的组。

工作的正则表达式几乎相同,除了它使用3, 2, 1的顺序(第一组想要大小为3,第二组想要大小为2,第三组想要大小为1):

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

到工作正则表达式的链接:https://regex101.com/r/wTHAma/1

获取仅聚集的项。
仍然是无序簇,但是组1、3、5包含了1、2、3
字符簇的字符。你可以对第1、3、5组的匹配位置进行排序,得到字符顺序,例如aaabbc将是3 2 1
匹配位置顺序的字符数。

(?m)^(?:(?!1|3|5)(?:(.)()|(.)3()|(.)55())){3}(?=246)$

https://regex101.com/r/O8Pmgs/1

仅使用查找头获取非聚集字符,
这似乎对我有用。这个可能无法获得顺序,例如bcbbac将是? ? ?,即使它将正确匹配。

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

https://regex101.com/r/WdTw1u/1

最新更新