Разбиение строки на группы в регулярных выражениях

177
08 июля 2019, 01:20

Хочу проверить строку на наличие хаотически выставленных букв разных регистров. Для примера строка на входе:

Это стрОка... это сТроКа.

Выходная строка:

Это строка... Это строка.

Установку первой буквы предложения делаю так:

private static final String DOT_REGEX = "\\s*(?<!\\.)\\.(?!\\.)\\s*";
private static final String MULTI_DOT_REGEX = "\\s*\\.{3}\\s*";
private static final String FORMAT_CASE = "(?:^| )^\\w" + "|" + MULTI_DOT_REGEX + "\\w" + "|" + DOT_REGEX + "\\w";

Функция которая обрабатывает строку и возвращает готовый результат:

private static String getFormatCaseString(String targetString){
        Matcher matcher = Pattern.compile(FORMAT_CASE).matcher(targetString);
        StringBuffer stringBuffer = new StringBuffer();
        while (matcher.find()){
            matcher.appendReplacement(stringBuffer, matcher.group().toUpperCase());
        }
        matcher.appendTail(stringBuffer);
        return stringBuffer.toString();
    }

Идея в том что бы разбить предложение на две группы: первая это первые буквы нового предложения (которые и устанавливаются в UpperCase) и вторая это все остальные буквы которые выставляются в нижнем регистре. Как это сделать?

Answer 1

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

String targetString = "Это стрОка... это сТроКа.";
Matcher matcher = Pattern.compile("(?Us)(\\w)(.*?(?:\\.{3}|(?<!\\.)\\.(?!\\.)))").matcher(targetString);
StringBuffer stringBuffer = new StringBuffer();
while (matcher.find()){
    matcher.appendReplacement(stringBuffer, 
        matcher.group(1).toUpperCase() + 
        matcher.group(2).toLowerCase()
    );
}
matcher.appendTail(stringBuffer);
System.out.println(stringBuffer.toString());
// = Это строка... Это строка.

Подробности

  • (?Us) - модификаторы Pattern.UNICODE_CHARACTER_CLASS (чтобы \w находил и русские буквы) и Pattern.DOTALL (чтобы . находил символы перевода строки)
  • (\\w) - Захватывающая группа №1: буква, цифра или _ (это значение будет приведено к верхнему регистру - matcher.group(1).toUpperCase())
  • (.*?(?:\\.{3}|(?<!\\.)\\.(?!\\.))) - Захватывающая группа №2 (это значение будет приведено к нижнему регистру - matcher.group(2).toLowerCase()):
    • .*? - 0 и более любых символов, как можно меньше
    • (?: - начало незахватывающей группы
      • \\.{3} - три точки
      • | - или
      • (?<!\\.)\\.(?!\\.) - точка, перед и за которой нет других точек
    • ) - конец незахватывающей группы
READ ALSO
Можно ли писать на Java для iOS?

Можно ли писать на Java для iOS?

До меня дошли страшные слухи, что на iOS нет JVMБолее того, до меня дошли страшные слухи, что будто бы фирма Эппл не разрешает ставить JVM на iOS

201
Как создать корзину в Java? [закрыт]

Как создать корзину в Java? [закрыт]

Нужно создать интернет-магазинПользователь выбирает товары, они складываются в корзину

181
Проблема с выводом Объекта из файла

Проблема с выводом Объекта из файла

Создаю небольшое приложение, при нажатии на кнопку регистрации создается объект

169
Цвет ссылки текущей страницы

Цвет ссылки текущей страницы

Есть листинг (новостей), а данный момент выглядит это так:

181