【问题标题】:Regular Expression to detect repetition within a string正则表达式检测字符串中的重复
【发布时间】:2009-06-03 09:45:17
【问题描述】:

是否可以用正则表达式检测重复的数字模式?

例如,如果我有以下字符串“034503450345”,是否可以匹配重复的序列0345?我觉得这超出了正则表达式的范围,但我想我还是会在这里问一下,看看我是否遗漏了什么。

【问题讨论】:

  • 您使用什么语言/平台?
  • 我正在使用 C#。我需要的只是正则表达式,所以我已经实现了 RichieHindle 的解决方案,并已经根据我的测试数据对其进行了验证!我还从 Peter Boughton 的出色评论的正则表达式中学到了很多东西。谢谢你们!
  • @MarkWithers 我正在处理同样的问题。您能否更具体一点,并告诉我更多有关您的解决方案的信息?谢谢
  • @user2179427 不是真的,那是 6 年前的事了,所以我再也无法访问源代码了。但是,此问题中所有投票赞成的正则表达式模式都有效,因此这只是查找如何用您选择的语言执行正则表达式的一个案例

标签: c# regex


【解决方案1】:

此表达式将匹配一个或多个重复组:

(.+)(?=\1+)


这是分解的相同表达式,(使用注释,因此它仍然可以直接用作正则表达式)。

(?x)  # enable regex comment mode
(     # start capturing group
.+    # one or more of any character (excludes newlines by default)
)     # end capturing group
(?=   # begin lookahead
\1+   # match one or more of the first capturing group
)     # end lookahead


要匹配特定模式,请将 .+ 更改为该模式,例如\d+ 匹配一个或多个数字,\d{4,} 匹配 4 个或更多数字。

要匹配特定数量的模式,请将\1+ 更改为\1{4},重复四次。

要让重复不相邻,您可以在前瞻中添加.*?

【讨论】:

  • 很好的例子,解释得很好
  • 很好的解释。优秀的扩展。谢谢!! +1
【解决方案2】:

是的,你可以 - 这是一个 Python 测试用例

import re
print re.search(r"(\d+).*\1", "8034503450345").group(1)
# Prints 0345

正则表达式的意思是“找到一些数字序列,然后是任意数量的其他东西,然后再次找到相同的序列。”

在一个几乎不相关的注释中,这是我最喜欢的正则表达式之一 - 质数检测器:

import re
for i in range(2, 100):
    if not re.search(r"^(xx+)\1+$", "x"*i):
        print i

【讨论】:

  • 您的素数检测器发现 0 和 1 是素数 :-)
  • 知道为什么下面的例子匹配8而不是0345吗?在[18]中: foo = re.search(r"(\d+).*\1", "80345824103452420345") 在[19]中: foo.groups() 出[19]: ('8',)跨度>
  • @balpha: 好的 pont - 已修复。 8-)
  • @Hank Gay:它将匹配它找到的第一个重复组,在这种情况下是“8”。使用更多的“\d”或大括号来设置最小长度。
  • @RichieHindle:谢谢。我以某种方式说服自己(起初)它是匹配最长的,而不是第一个。
【解决方案3】:

只是为 RichieHindle 的(正确)答案添加注释:

请注意,虽然 Python 的正则表达式实现(以及许多其他实现,例如 Perl 的)可以做到这一点,但这不再是狭义上的正则表达式。

您的示例不是正则语言,因此不能由纯正则表达式处理。参见例如优秀的Wikipedia article了解详情。

虽然这主要只是学术兴趣,但也有一些实际后果。与这种情况相比,真正的正则表达式可以更好地保证最大运行时间。因此,您可能会在某些时候遇到性能问题。

并不是说这不是一个好的解决方案,但您应该意识到您已处于正则表达式(即使是扩展形式)的能力极限,并且可能希望在出现问题时考虑其他解决方案。

【讨论】:

    【解决方案4】:

    这是 C# 代码,它使用反向引用构造来查找重复的数字。它将与 034503450345、123034503450345、034503450345345、232034503450345423 一起使用。正则表达式更容易理解。

    /// <summary>
    /// Assigns repeated digits to repeatedDigits, if the digitSequence matches the pattern
    /// </summary>
    /// <returns>true if success, false otherwise</returns>
    public static bool TryGetRepeatedDigits(string digitSequence, out string repeatedDigits)
    {
        repeatedDigits = null;
    
        string pattern = @"^\d*(?<repeat>\d+)\k<repeat>+\d*$";
    
        if (Regex.IsMatch(digitSequence, pattern))
        {
            Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
            repeatedDigits = r.Match(digitSequence).Result("${repeat}");
            return true;
        }
        else
            return false;
    }
    

    【讨论】:

    • 非常好!我喜欢使用命名组。生产质量代码,注释并准备复制。非常感谢!
    【解决方案5】:

    使用正则表达式重复: 酒吧{2,} 查找带有两个或更多条的文本: 野蛮人 野蛮人 ...

    【讨论】:

      猜你喜欢
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多