【问题标题】:Repeating pattern using regex in C#在 C# 中使用正则表达式重复模式
【发布时间】:2019-11-16 22:11:45
【问题描述】:

我有一串单词:

词暗王辉我们结束你好再见低翼

我需要找到第一个单词的最后一个字母与后面单词的第一个字母匹配的单词(例如:worD Dark)。

我写了一个正则表达式:

\b\w*(\w)\W\1\w*\b

目前已成功连续找到 2 个单词(Regex.Matches[0].Value = "word dark" ; Regex.Matches[1].Value = "king glow" 等)

我需要一个正则表达式,可以将其读取为模式 (Regex.Matches[0].Value = "word dark king glow we end" ; Regex.Matches[1].Value = "low wing")。

我应该如何处理这个问题?

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    这里记录一个非常有表现力的非正则表达式版本。我不需要图片;)

    static IEnumerable<(string W1, string W2)> GetPairs1(string input)
    {
        var words = input.Split(' ', StringSplitOptions.RemoveEmptyEntries);
    
        if (!words.Any()) yield break;
    
        for( int i = 1; i < words.Length; i++) 
            if(words[i][0] == words[i-1][words[i-1].Length-1]) 
                yield return (words[i-1], words[i]);
    }
    

    测试

    public static async Task Main()
    {
        var input = "word dark king glow we end hello bye low wing";
    
        foreach (var p in GetPairs1(input)) 
            Console.WriteLine($"{p.W1} {p.W2}");
    }
    

    输出

    word dark
    dark king
    king glow
    glow we
    we end
    low wing
    

    【讨论】:

      【解决方案2】:

      我还要capture最后一个单词字符,检查lookahead内部是否it匹配下一个单词的第一个字符,将所有字符放入group进行重复,如果条件成功,匹配以下词。

      (?i)(?:\b\w*(\w) +(?=\1))+\w+
      

      See this demo at regex101

      使用 caseless flag (?i) 用于捕获 a 匹配以下单词中的 A

      【讨论】:

      • 我仍然无法理解它是如何工作的。但是,另一方面,至少它有效^^
      • @GytisDokšas 前瞻没有消耗任何东西。想想没有(?= +\1) 的模式,它基本上就是(?:\b\w+ )+\w+。但是我们捕获第一个单词中的最后一个字母,并且只有在下一个单词的第一个字母匹配的条件成功时才继续。
      • 附加问题:如何在单词之间添加标点符号(例如 word, dayword!day(带/或不带空格))
      • @GytisDokšas 正如你对\W+ 所做的那样,而不是空格 (demo) 或任何你认为非单词字符的东西。
      • 我自己用 \W+ 试过,先没用,在你的建议后重试,现在它确实有效,dang,正则表达式是一些巫术魔法^^
      【解决方案3】:

      好问题,这里有good answer

      具有正向预测

      我猜,

      (?is)\w*(\w)(?= (\1)\w*)
      

      可能更接近一些,但可能存在边缘情况,您可能希望在此块中查看积极的前瞻:

      (?= (\1)\w*)
      

      RegEx Demo 1


      积极向后看

      如果/根据需要和编码,您还可以向后看,捕捉事物,可能使用类似于以下的表达式:

      (?is)(?<=([a-z])\s)(\1)([a-z]*)
      

      RegEx Demo 2

      测试

      using System;
      using System.Text.RegularExpressions;
      
      public class Example
      {
          public static void Main()
          {
              string pattern = @"(?is)\w*(\w)(?= (\1)\w*)";
              string input = @"word dark king glow we end hello bye low wing
      word Dark King Glow We End hello bye LoW wing";
      
              foreach (Match m in Regex.Matches(input, pattern))
              {
                  Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
              }
          }
      }
      

      如果您希望简化/修改/探索表达式,在regex101.com 的右上角面板中已对此进行了说明。如果您愿意,您还可以在 this link 中观看它如何与一些示例输入匹配。



      复杂性

      一般来说,环顾四周并不是真正对复杂性友好的方法,但我现在想不出更好的方法。

      【讨论】:

      • 它更接近但仍然不是我想要的。假设我需要在更大的文本中使用此模式找到最长的(如字数)组合。有了更多的函数,就可以用你的表达式来实现它,但如果有办法将它作为整个值来获取它会更简单(目前它会创建许多 Regex.Matches 并增加复杂性)
      猜你喜欢
      • 1970-01-01
      • 2012-07-03
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多