【问题标题】:How to find repeatable characters如何找到可重复的字符
【发布时间】:2012-04-24 08:52:47
【问题描述】:

我不明白如何解决以下问题:

我输入了字符串“aaaabaa”,我正在尝试搜索字符串“aa”(我正在寻找字符的位置) 预期结果是 0 1 2 5

  • aa aabaa
  • 一个 aa abaa
  • aa aa
  • aaaab aa

我已经使用另一种方法(非正则表达式)解决了这个问题。 但我需要一个 RegEx 我是 RegEx 的新手,所以谷歌搜索真的帮不了我。 任何帮助表示赞赏!谢谢!

附: 我尝试使用(aa)*"\b(\w+(aa))*\w+" 但这些表达式是错误的

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    你可以通过使用前瞻来解决这个问题

    a(?=a)
    

    将找到后跟另一个“a”的每个“a”。

    如果你想更普遍地这样做

    (\p{L})(?=\1)
    

    这将找到后跟相同字符的每个字符。每个找到的字母都存储在一个捕获组中(因为有括号),然后positive lookahead assertion(?=...))通过使用\1(在\1中有匹配字符)重用这个capturing group存储)

    \p{L} 是一个带有“字母”类别的 unicode 代码点

    代码

    String text = "aaaabaa";
    Regex reg = new Regex(@"(\p{L})(?=\1)");
    
    MatchCollection result = reg.Matches(text);
    
    foreach (Match item in result) {
        Console.WriteLine(item.Index);
    }
    

    输出

    0
    1
    2
    5

    【讨论】:

    • 我想知道如何找到整个单词,而不仅仅是“aa”,而是随机模式,例如“baaaaabbaa”中的“abba”
    • @PaulKovalev Match.index 为您提供索引。
    • @PaulKovalev “找到一个完整的单词”是什么意思?
    • @stema 谢谢!我希望会有所帮助!
    • @stema 我的意思是如果它是随机字符串中的随机搜索模式(这是更常见的问题),例如“baaaaabbaa”中的“abba”等。我可以定义一些我在看的词的边界吗为了?我的意思是 WordIWantToFind。据我了解 \p{L} 解决了这个问题。
    【解决方案2】:

    以下代码可以与任何正则表达式一起使用,而无需更改实际表达式:

            Regex rx = new Regex("(a)\1"); // or any other word you're looking for.
    
            int position = 0;
            string text = "aaaaabbbbccccaaa";
            int textLength = text.Length;
    
            Match m = rx.Match(text, position);
    
            while (m != null && m.Success)
            {
                Console.WriteLine(m.Index);
    
                if (m.Index <= textLength)
                {
                    m = rx.Match(text, m.Index + 1);
                }
                else
                {
                    m = null;
                }
            }
    
            Console.ReadKey();
    

    它使用选项来更改每个连续搜索的正则表达式搜索的开始索引。实际问题来自于 Regex 引擎在默认情况下总是会在上一次匹配之后继续搜索。所以它永远不会在另一个匹配中找到可能的匹配,除非你通过使用 Look ahead 构造或手动设置开始索引来指示它。

    另一个相对简单的解决方案是将整个表达式保持向前看:

            string expression = "(a)\1"
            Regex rx2 = new Regex("(?=" + expression + ")");
            MatchCollection ms = rx2.Matches(text);
            var indexes = ms.Cast<Match>().Select(match => match.Index);
    

    这样,引擎会自动将索引每找到一个匹配项向前推进一个。

    From the docs:

    当通过调用 NextMatch 方法重复匹配尝试时,正则表达式引擎会给予空匹配特殊处理。通常,NextMatch 会在前一个匹配停止的位置开始搜索下一个匹配。但是,在空匹配之后,NextMatch 方法会在尝试下一个匹配之前前进一个字符。此行为保证正则表达式引擎将通过字符串进行。否则,由于空匹配不会导致任何向前移动,因此下一个匹配将从与上一个匹配完全相同的位置开始,并且会重复匹配相同的空字符串。

    【讨论】:

      【解决方案3】:

      试试这个:

      How can I find repeated characters with a regex in Java?

      它在 java 中,但是有正则表达式和非正则表达式的方式。 C# Regex 与 Java 方式非常相似。

      【讨论】:

      • 实际上并非如此,因为它没有考虑重叠匹配。
      猜你喜欢
      • 1970-01-01
      • 2020-11-24
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 2021-05-24
      • 1970-01-01
      相关资源
      最近更新 更多