2008-11-26 5 views
28

Я не могу найти ответ на эту проблему, и мне интересно, существует ли она. Упрощенный пример:Перекрытие совпадений в Regex

Рассмотрим строку «nnnn», где я хочу найти все совпадения «nn», но также и те, которые перекрываются друг с другом. Таким образом, регулярное выражение будет предоставлять следующие 3 матча:

  1. пп пп
  2. п пп п
  3. пп пп

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

ответ

19

Возможным решением может быть использовать positive look behind:

(?<=n)n 

Это даст вам конечное положение:

  1. * п *** п ** пп  
  2. n * n *** n ** n  
  3. nn * n *** n **

Как упоминалось на Timothy Khouri, положительный предпросмотр более интуитивным

Я предпочел бы, чтобы его предложение (?=nn)n более простой вид:

(n)(?=(n)) 

Это будет ссылаться на первую позицию строк, которые вы хотите , и будет захватывать второе n в группе (2).

Это так, потому что:

  • Любое допустимое регулярное выражение может быть использовано внутри опережающего просмотра.
  • Если он содержит скользящие круглые скобки, то обратные ссылки будут сохранены.

Таким образом, группа (1) и группа (2) будут захватывать все, что 'n' представляет (даже если это сложное регулярное выражение).

1

AFAIK, нет простого регулярного способа сделать это сразу (т. Е. Вернуть три захвата, которые вы запрашиваете без цикла).

Теперь вы можете найти образец один раз и выполнить цикл поиска, начиная со смещения (найденная позиция + 1). Следует комбинировать использование регулярных выражений с простым кодом.

[EDIT] Отлично, я занижен, когда я в основном сказал, что Ян показал ...
[EDIT 2] Чтобы быть ясным: ответ Яна лучше. Не более точно, но, безусловно, более подробно, он заслуживает выбора. Я просто не понимаю, почему мой занижен, так как я до сих пор не вижу в нем ничего неправильного. Не очень, просто раздражает.

+0

Ударьте меня к ней на 1 секунду, я выведу свой идентичный ответ! – 2008-11-26 11:58:43

+0

неправда, см. Ответ «VonC» – 2008-11-26 12:22:43

+0

@Timothy: это не будет делать захват, и вам все равно придется зацикливаться на результатах, поэтому я не уверен в преимуществах ... – PhiLho 2008-11-26 13:42:34

21

Использование lookahead с группой захвата работает, за счет того, что ваше регулярное выражение работает медленнее и сложнее. Альтернативное решение - указать метод Regex.Match(), где должна начинаться следующая попытка совпадения. Попробуйте следующее:

Regex regexObj = new Regex("nn"); 
Match matchObj = regexObj.Match(subjectString); 
while (matchObj.Success) { 
    matchObj = regexObj.Match(subjectString, matchObj.Index + 1); 
} 
Смежные вопросы