2015-11-17 3 views
2

У меня есть регулярное выражение, которое делает в значительной степени именно то, что я хочу: \.?(\w+[\s|,]{1,}\w+[\s|,]{1,}\w+){1}\.?Capture всех группы, которые соответствуют регулярному выражению

Значения это фиксирует случаи из 3 слов в строке, не отделенное ничем, кроме пробелов и запятых (так частей только предложений). Однако я хочу, чтобы это соответствовало каждый экземпляр из 3 слов в предложении.

Так что в этом ультра простой пример:

Hi this is Bob.

Там должно быть 2 захватывает - «Привет это» и «это Боб». Кажется, я не могу понять, как заставить механизм регулярного выражения разбирать все заявление таким образом. Есть предположения?

+2

Вы можете получить два матча с [ '(= \ Ь (\ W + (?:? [\ с,] + \ ш +) {2}) \ б) '] (https://regex101.com/r/yC5dG5/2) и получить текст, который вам нужен из группы 1. –

+0

Строго говоря, может быть, нет, но с петлей или какой-то специальной функцией вы можете это сделать. На каком языке вы используете? – blcook223

+0

!!! @стрибижев, это ответ! –

ответ

2

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

Использование

(?=\b(\w+(?:[\s,]+\w+){2})\b) 

Посмотреть regex demo

The unanchored положительные тесты LOOKAHEAD для пустой строки матча в каждой позиции строки. Он не потребляет символов, но все равно может возвращать субматрицы, полученные с помощью групп захвата.

пробоя Regex:

  • \b - слово граница
  • (\w+(?:[\s,]+\w+){2}) - 3 "слова" разделены , или пробелом.
    • \w+ - 1 или более буквенно-цифровые символы следуют с
    • (?:[\s,]+\w+){2} - 2 последовательностей 1 или более пробелами или запятыми, а затем 1 или более алфавитно-цифровых символов.

Эта модель просто положить в группу захвата (...), который помещается внутри опережающего просмотра (?=...).

Границы слова важны в этом выражении, потому что \b предотвращает совпадение внутри слово (между двумя буквенно-цифровыми символами). Поскольку lookahead не привязан, он проверяет все позиции внутри входной строки, а \b служит ограничением на то, где можно вернуть совпадение.

В C# вам просто нужно собрать все match.Groups[1].Value s, например. как это:

var s = "Hi this is Bob."; 
var results = Regex.Matches(s, @"(?=\b(\w+(?:[\s,]+\w+){2})\b)") 
         .Cast<Match>() 
         .Select(p => p.Groups[1].Value) 
         .ToList(); 

Посмотреть IDEONE demo

+0

Привет @стрибижев, как граница слова работает в этом решении? Означает ли это, что для каждого слова, найденного в целевой строке, проверьте следующее условие (следующим условием является слово, за которым следуют 2 пробела пробела и слово)? –

+0

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

+0

Если кто-нибудь в будущем пытается использовать этот шаблон регулярного выражения в .NET - мне приходилось обращаться к совпадениям через 'foreach (совпадение совпадений в совпадениях) {var words = match.Groups [1] .ToString(). Split (''); } ' –

Смежные вопросы