Как изменить регистр только текущей буквы на RE?

#java #regex

#java #регулярное выражение

Вопрос:

Мне нужно изменить регистр первой буквы каждого слова

  String regex = "\b\w";
        Pattern p = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher m = p.matcher(input);
        while(m.find()){    
            input = input.replaceAll("\b" m.group(),switchCase(m.group()));
        }
 

если слова имеют одинаковый первый регистр, он также изменит предыдущий

пример

Input: hello all Hello

My Output: hello All hello

Correct output: Hello All hello

как я могу это исправить?

Ответ №1:

В Java 11 я бы сделал это следующим образом, чтобы получить полную поддержку Unicode:

 public static String switchCase(String input) {
    return Pattern.compile("\b\p{L}").matcher(input)
                  .replaceAll(mr -> switchCase(mr.group().codePointAt(0)));
}

private static String switchCase(int codePoint) {
    return Character.toString(Character.isLowerCase(codePoint)
                              ? Character.toTitleCase(codePoint)
                              : Character.toLowerCase(codePoint));
}
 

Тест

 System.out.println(switchCase("hello all Hello"));
 

Вывод

 Hello All hello
 

Поскольку Character.toString​(int codePoint) не был добавлен до Java 11, второй метод необходимо изменить для Java 1.5 на Java 10:

 private static String switchCase(int codePoint) {
    return new String(new int[] { Character.isLowerCase(codePoint)
                                  ? Character.toTitleCase(codePoint)
                                  : Character.toLowerCase(codePoint) }, 0, 1);
}
 

Поскольку replaceAll​(Function<MatchResult,​String> replacer) не был добавлен до Java 9, первый метод необходимо изменить для Java 1.5 на Java 8:

 public static String switchCase(String input) {
    StringBuffer buf = new StringBuffer();
    Matcher m = Pattern.compile("\b\p{L}").matcher(input);
    while (m.find())
        m.appendReplacement(buf, switchCase(m.group().codePointAt(0)));
    return m.appendTail(buf).toString();
}