Используйте Java и RegEx для преобразования регистра в строке

Проблема: повернуть

"My Testtext TARGETSTRING My Testtext" 

в

"My Testtext targetstring My Testtext"

Perl поддерживает операцию "\ L", которую можно использовать в строке замены.

Pattern-Class не поддерживает эту операцию:

Конструкции Perl, не поддерживаемые этим классом: [...] Операции предварительной обработки \ l \ u, \ L и \ U. https://docs.oracle.com/javase/10/docs/api/java/util/regex/Pattern.html


person Andreas    schedule 05.05.2010    source источник
comment
Я этого не понимаю. Что не так с "my testtext TARGETSTRING my testtext".toLowerCase();?   -  person WVrock    schedule 09.06.2015
comment
Извините, пример был неудачным. toLowerCase не работает с My Testtext TARGETSTRING My Testtext   -  person Andreas    schedule 10.06.2015


Ответы (5)


Вы не можете сделать это в регулярном выражении Java. Вам придется вручную выполнить постобработку, используя _ 1_ и toLowerCase() вместо этого.

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

    String text = "no way oh my god it cannot be";
    Matcher m = Pattern.compile("\\b\\w{3,}\\b").matcher(text);

    StringBuilder sb = new StringBuilder();
    int last = 0;
    while (m.find()) {
        sb.append(text.substring(last, m.start()));
        sb.append(m.group(0).toUpperCase());
        last = m.end();
    }
    sb.append(text.substring(last));

    System.out.println(sb.toString());
    // prints "no WAY oh my GOD it CANNOT be"

Примечание к appendReplacement и appendTail

Обратите внимание, что приведенное выше решение использует substring и управляет индексом tail и т. Д. Фактически, вы можете обойтись без них, если используете _ 8_ и appendTail.

    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        m.appendReplacement(sb, m.group().toUpperCase());
    }
    m.appendTail(sb);

Обратите внимание, что sb теперь является StringBuffer вместо StringBuilder. Пока Matcher не обеспечит StringBuilder перегрузок, вы застрянете с более медленным StringBuffer, если хотите использовать эти методы.

Вам решать, стоит ли платить за меньшую эффективность ради лучшей читаемости или нет.

Смотрите также

person polygenelubricants    schedule 05.05.2010
comment
Начиная с Java 9, Matcher.appendReplacement содержит перегрузку для StringBuilder - person MoonFruit; 16.06.2020

Чтобы сделать это на уровне регулярного выражения, вы должны использовать \U для включения режима верхнего регистра и \E для его выключения. Вот пример использования этой функции в диалоговом окне IntelliJ IDEA find-and-replace, которое преобразует набор полей класса в утверждения JUnit (всплывающая подсказка в IDE является результатом преобразования find-and-replace):

введите описание изображения здесь

person Andriy Kryvtsun    schedule 02.02.2017
comment
Это специфично для IntelliJ, простые регулярные выражения Java этого не поддерживают. - person ddekany; 24.03.2017
comment
Также есть \L для режима нижнего регистра (который также заканчивается на \E). Конечно, это тоже специфично для IntelliJ. - person ddekany; 24.03.2017
comment
@ddekany технически вы правы: JDK lib его не поддерживает (docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html см. 'Сравнение с Perl 5'), но я предполагаю, что IntelliJ IDEA использует автономное регулярное выражение lib. - person Andriy Kryvtsun; 24.03.2017

Вы можете использовать группу захвата регулярных выражений (если вам действительно нужно использовать регулярное выражение, то есть то есть, если "TARGETSTRING" достаточно сложный и "обычный" достаточно, чтобы оправдать обнаружение регулярным выражением).
Затем вы применили бы toLowerCase() к группе №1.

import java.util.regex.*;

public class TargetToLowerCase {

  public static void main(String[] args) {
    StringBuilder sb= new StringBuilder(
            "my testtext TARGETSTRING my testtext");
    System.out.println(sb);
    String regex= "TARGETSTRING ";
    Pattern p = Pattern.compile(regex); // Create the pattern.
    Matcher matcher = p.matcher(sb); // Create the matcher.
    while (matcher.find()) {
      String buf= sb.substring(matcher.start(), matcher.end()).toLowerCase();
      sb.replace(matcher.start(), matcher.end(), buf);
    }
    System.out.println(sb);
  }
}
person VonC    schedule 05.05.2010
comment
Это должен быть псевдокод? Очевидно, что "$1".toLowerCase() сначала оценивается, поэтому replaceAll просто видит "$1", что означает, что он ничего не делает. - person Matthew Flaschen; 05.05.2010
comment
@Matthew: верно, реальное решение на основе регулярных выражений немного сложнее. Я изменил ответ, чтобы отразить это. - person VonC; 05.05.2010
comment
Уловка NICE, использующая sb.replace, чтобы воспользоваться тем фактом, что длина замены всегда (?) Равна длине исходной строки. В противном случае это не сработало бы. Очень хорошо! - person polygenelubricants; 05.05.2010
comment
К сожалению, переключение регистра не сохраняет длину строки. См. Сохраняет ли Java toLowerCase () исходную длину строки?. - person MicSim; 13.01.2015

Java9 +

В Java 9+ вы можете использовать String :: replaceAll, где вы можете использовать Function<MatchResult, String>, например, мы используем пример полигенные смазочные материалы:

String text = "this is just a test which upper all short words";
String regex = "\\b\\w{0,3}\\b";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
String result = matcher.replaceAll(matche -> matche.group().toUpperCase());

System.out.println(result);

Или просто :

String result = Pattern.compile(regex)
        .matcher(text)
        .replaceAll(matche -> matche.group().toUpperCase());

Вывод

this IS just A test which upper ALL short words
     ^^      ^                  ^^^
person YCF_L    schedule 26.04.2018

Как насчет этой функции преобразования в "Java 8"

/**
 * Searches the given pattern in the given src string and applies the txr to the
 * matches
 * 
 * @param src     The string to be converted
 * @param pattern the pattern for which the transformers to be applied.
 * @param txr     The transformers for the mathed patterns.
 * @return The result after applying the transformation.
 */
private static String fromTo(String src, String pattern, Function<String, String> txr) {
    Matcher m = Pattern.compile(pattern).matcher(src);

    StringBuilder sb = new StringBuilder();
    int last = 0;

    while (m.find()) {
        sb.append(src.substring(last, m.start()));
        sb.append(txr.apply(m.group(0)));
        last = m.end();
    }
    sb.append(src.substring(last));
    return sb.toString();
}
person Kannan Ramamoorthy    schedule 15.10.2019