Перекрывающиеся спички в Regex - PullRequest
32 голосов
/ 26 ноября 2008

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

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

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

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

Ответы [ 3 ]

25 голосов
/ 26 ноября 2008

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

Regex regexObj = new Regex("nn");
Match matchObj = regexObj.Match(subjectString);
while (matchObj.Success) {
    matchObj = regexObj.Match(subjectString, matchObj.Index + 1); 
}
21 голосов
/ 26 ноября 2008

Возможным решением может быть использование положительного взгляда за :

(?<=n)n

Это даст вам конечную позицию:

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

Как упомянул Тимоти Хоури , позитивный взгляд более интуитивен

Я бы предпочел к его предложению (?=nn)n более простую форму:

(n)(?=(n))

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

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

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

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

1 голос
/ 26 ноября 2008

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

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

[РЕДАКТИРОВАТЬ] Отлично, я опущен, когда я в основном сказал то, что показал Ян ...
[РЕДАКТИРОВАТЬ 2] Чтобы быть ясным: ответ Яна лучше. Не более точный, но, конечно, более подробный, он заслуживает выбора. Я просто не понимаю, почему мое голосование понижено, так как я все еще не вижу в нем ничего неправильного. Ничего страшного, просто раздражает.

...