2015-10-13 2 views
3

У меня есть эта RegEx, который находит любую перестановку с одним А, один В и два С-х.NET Regex перекрывающихся совпадает с последним символом

(?:(?<A>A)|(?<B>B)|(?<C>C)){4}(?<-A>)(?<-B>)(?<-C>){2} 

, например, для этой комбинации мы имеем 3 матча (позиции 1, 7, 15)

ABCCABCABCABCAABCC 

Если добавить опережения утверждения можно подсчитать количество совпадений, начиная со следующей позицией, а не в следующей позиции после полной последовательности

(?=(?<value>(?:(?<A>A)|(?<B>B)|(?<C>C)){4}(?<-A>)(?<-B>)(?<-C>){2})) 
^               ^

И мы имеем 7 матчей в этом примере

1. ABCC 
2. BCCA 
3. CCAB 
4. CABC 
7. CABC 
10. CABC 
15. ABCC 

Как stribizhev помогли в этом предыдущем посте: .NET Regex number of overlaping matches

Теперь мне нужно найти последовательность всех возможных комбинаций, например, , ABC, но 3 раза и перекрытие одного символа.

Например, для следующей последовательности:

AABCBACBCCAACCB 

Это будет иметь последовательность в положении 1

Pos 1. ABC 
Pos 3. CBA 
Pos 5. ACB 

Так выглядит последовательность, где мы имеем любую комбинацию ABC, которая появляется в 3 раза в строке, но взяв в качестве первого символа последний из предыдущего совпадения.

Я надеюсь, что я объяснил хорошо ..

Как я могу это сделать?

+0

вам нужно сделать, это делать с регулярным выражением? Даже если это возможно, я подозреваю, что повторение строки и подсчет соответствующих символов будет более быстрым и чистым. – LukeH

+0

@sln Похоже, что OP использует ноль на основе 'Pos' для последнего примера. – PetSerAl

+0

@PetSerAl - прямо ты, я ослеп. – sln

ответ

3

Вы можете достичь этого с помощью простой модификации до @stribizhev.

Во-первых, у вас есть только C не два:

(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>) 

Как вы хотите, чтобы начать новый матч с последнего символа, вы можете использовать опережения утверждение и захватить только два символа после него:

(?=(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>)).. 

Теперь вы просто повторяете это три раза и захватываете только один последний символ:

(?:(?=(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>))..){3}. 
+0

Спасибо за ответ. Я думаю, что мы приближаемся. Я отредактировал свой вопрос, так как я думаю, что не очень хорошо объяснил. –

+0

@MikeJohnson Я отредактировал свой ответ. – PetSerAl

+0

Это здорово !!! Оно работает. Спасибо –

0

Вот как вы можете добиться того, что в C# - обратите внимание, что s переменная будет изменяться в течение всего процесса, поэтому клонировать его перед или использовать копию:

var s = "AABCBACBCCAACCB AABCBACBCCAACCB AABBBAABCCAACCB"; 
var rx = new Regex("(?=(?<value>(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>)))"); 
var m = rx.Match(s); 
while (m.Success) 
{ 
    var list = new List<string>(); 
    list.Add(m.Groups["value"].Value); 
    s = s.Substring(m.Groups["value"].Index+m.Groups["value"].Length-1); 
    m = rx.Match(s); 
    if (m.Success && m.Groups["value"].Index == 0) 
    { 
     list.Add(m.Groups["value"].Value); 
     s = s.Substring(m.Groups["value"].Index+m.Groups["value"].Length-1); 
     m = rx.Match(s); 
     if (m.Success && m.Groups["value"].Index == 0) 
     { 
      list.Add(m.Groups["value"].Value); 
      Console.WriteLine(string.Join(", ", list)); 
      s = s.Sustring(m.Groups["value"].Index+m.Groups["value"].Length-1); 
      m = rx.Match(s); 
     } 
    } 
} 

См IDEONE demo