Жадный, не жадный, всесожжение в C # Regex - PullRequest
21 голосов
/ 10 октября 2010

Как я могу получить все совпадения в следующем примере:

// Only "abcd" is matched
MatchCollection greedyMatches = Regex.Matches("abcd", @"ab.*");

// Only "ab" is matched
MatchCollection lazyMatches   = Regex.Matches("abcd", @"ab.*?");

// How can I get all matches: "ab", "abc", "abcd"

P.S .: Я хочу, чтобы все совпадения были общими. Приведенный выше пример является лишь примером.

Ответы [ 3 ]

19 голосов
/ 10 октября 2010

Вы можете использовать что-то вроде:

MatchCollection nonGreedyMatches = Regex.Matches("abcd", @"(((ab)c)d)");

Тогда у вас должно быть три обратных ссылки с ab, abc и abcd.

Но, если честно, такого рода регулярные выражения не имеют особого смысла, особенно когда они становятся больше, они становятся нечитаемыми.

Edit:

MatchCollection nonGreedyMatches = Regex.Matches("abcd", @"ab.?");

И, между прочим, вы получили ошибку там. Это может соответствовать только ab и abc (читай: ab + любой (необязательный) символ

Ленивая версия:

MatchCollection greedyMatches    = Regex.Matches("abcd", @"ab.*");

есть:

MatchCollection nonGreedyMatches    = Regex.Matches("abcd", @"ab.*?");
4 голосов
/ 10 октября 2010

Если решение существует, оно может включать группу захвата и параметр RightToLeft:

string s = @"abcd";
Regex r = new Regex(@"(?<=^(ab.*)).*?", RegexOptions.RightToLeft);
foreach (Match m in r.Matches(s))
{
  Console.WriteLine(m.Groups[1].Value);
}

выход:

abcd
abc
ab

Я говорю «если», потому что, хотя он работает для вашего простого тестового примера, я не могу гарантировать, что этот трюк поможет с вашей реальной проблемой. Режим RightToLeft - это одна из более инновационных функций .NET, я не могу придумать другой вариант, который имеет что-то подобное. Официальная документация на него немногочисленна (мягко говоря), и пока, похоже, не так много разработчиков используют ее и делятся своим опытом в Интернете. Так что попробуйте и посмотрите, что получится.

1 голос
/ 10 октября 2010

Вы не можете получить три разных результата только из одного матча.

Если вы хотите сопоставить только «ab», вы можете использовать ab.? или a.{1} (или множество других опций)
Если вы хотите сопоставить только «abc», вы можете использовать ab. или a.{2} (или множество других опций)
Если вы хотите сопоставить только «abcd», вы можете использовать ab.* или a.{3} (или множество других опций)

...