Чтобы решить эту проблему с помощью одного цикла, вам нужно, чтобы ваш сопоставитель нашел либо слова, либо маркеры конца предложения, а затем сообщил вам, что он нашел.Это можно сделать с помощью «групп захвата».
String s = "Hello, user. How many words and sentences are there? Count them!";
int words = 0;
int sentences = 0;
Pattern pattern = Pattern.compile("(\\w+)|([.?!])");
Matcher matcher = pattern.matcher(s);
while(matcher.find()) {
if (matcher.group(1) != null)
words++;
else if (matcher.group(2) != null)
sentences++;
}
System.out.printf("%d words and %d sentences%n", words, sentences);
11 слов и 3 предложений
Объяснение регулярного выражения:
(\w+)|([.?!])
- послеперевод \\
в \
(___)________
- группа захвата # 1.
_\w+_________
- один или несколько символов слова.
_____|_______
- соответствует первой части выражения илиsecond.
______(_____)
- группа захвата # 2.
_______[.?!]_
- символ-терминатор предложения.
Первый вызов matcher.find()
будет соответствовать Hello
, записывая его как группу захвата.# 1.Следующий вызов пропускается через запятую и пробел и соответствует user
, снова записывая его как группу захвата # 1.Третий вызов соответствует периоду (.
) во второй части регулярного выражения, записывая его как группу захвата # 2.Это продолжается до совпадения восклицательного знака (!
).Следующий вызов matcher.find()
возвращает значение false, поскольку совпадений больше не найдено.
Операторы if
проверяют, были ли заполнены захваты группы № 1 или группы № 2, что определяет, будет ли слово илиОбнаружен терминатор предложения.