Регулярное выражение для преобразования CamelCase в Camel case в java


Я понимаю, почему желаемый результат не дается для преобразования с помощью regex строку FooBar to Foo_Bar который вместо этого дает Foo_Bar_. Я мог бы сделать что-нибудь со строкой.подстрока substring(0, string.length() - 2) или просто заменить последний символ, но я думаю, что есть лучшее решение для такого сценария.

вот код:

String regex = "([A-Z][a-z]+)";
String replacement = "_";

"CamelCaseToSomethingElse".replaceAll(regex, replacement); 

/*
outputs: Camel_Case_To_Something_Else_
desired output: Camel_Case_To_Something_Else
*/

вопрос: ищете более аккуратный способ получить желаемый результат?

9 59

9 ответов:

посмотреть этот вопрос и CaseFormat из гуавы

в вашем случае, что-то вроде:

CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");

свяжите нижний и верхний регистр как две группы, это будет ОК

public  class Main
{
    public static void main(String args[])
    {
        String regex = "([a-z])([A-Z]+)";
        String replacement = "_";
        System.out.println("CamelCaseToSomethingElse"
                           .replaceAll(regex, replacement)
                           .toLowerCase());
    }
}

вы можете использовать ниже код:

String replaceAll = key.replaceAll("(.)(\p{Upper})", "_").toLowerCase();

почему бы просто не сопоставить предыдущий символ как не начало строки $?

String text = "CamelCaseToSomethingElse";
System.out.println(text.replaceAll("([^_A-Z])([A-Z])", "_"));

обратите внимание, что эта версия является безопасным для выполнения на то, что уже верблюд случае.

добавить утверждение нулевой ширины lookahead.

http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html

читать документацию для (?=X) etc.

лично я бы на самом деле сплит строка, а затем рекомбинировать его. Это может быть даже быстрее, когда все сделано правильно, и это делает код намного проще для понимания, чем магия регулярных выражений. Не поймите меня неправильно: я люблю регулярные выражения. Но это не действительно аккуратное регулярное выражение, и это трансформация классическая задача обработать. Ведь кажется вы тоже хотите делать строчные буквы?

уродливый, но быстрый хак будет заменить (.)([A-Z]+) С _ а затем в нижнем регистре всю строку после этого (если вы не можете сделать perl-стиль extrended regexps, где вы можете в нижнем регистре заменить непосредственно!). Тем не менее я рассматриваю расщепление при переходе от Нижнего к верхнему, затем преобразование, а затем присоединение как правильное и самое четкий способ сделать это.

([A-Z][a-z\d]+)(?=([A-Z][a-z\d]+))

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

смотрите сюда:http://regexr.com?30ooo

public class ReplaceFromCameltoSnake {
    public static void main(String args[]){
        String s1=" totalAmountWithoutDiscount";  
        String replaceString=s1.replaceAll("([A-Z]+)","\_").toLowerCase(); 
        System.out.println(replaceString);  
    }
}

Я не могу предоставить регулярное выражение, это было бы безумно сложно в любом случае.

попробуйте эту функцию с автоматическим распознаванием сокращений.

к сожалению, Guava lib не автоматически обнаруживает аббревиатуры верхнего регистра, поэтому " bigCAT "будет преобразован в"BIG_C_A_T"

/**
 * Convert to UPPER_UNDERSCORE format detecting upper case acronyms
 */
private String upperUnderscoreWithAcronyms(String name) {
    StringBuffer result = new StringBuffer();
    boolean begin = true;
    boolean lastUppercase = false;
    for( int i=0; i < name.length(); i++ ) {
        char ch = name.charAt(i);
        if( Character.isUpperCase(ch) ) {
            // is start?
            if( begin ) {
                result.append(ch);
            } else {
                if( lastUppercase ) {
                    // test if end of acronym
                    if( i+1<name.length() ) {
                        char next = name.charAt(i+1);
                        if( Character.isUpperCase(next) ) {
                            // acronym continues
                            result.append(ch);
                        } else {
                            // end of acronym
                            result.append('_').append(ch);
                        }
                    } else {
                        // acronym continues
                        result.append(ch);
                    }
                } else {
                    // last was lowercase, insert _
                    result.append('_').append(ch);
                }
            }
            lastUppercase=true;
        } else {
            result.append(Character.toUpperCase(ch));
            lastUppercase=false;
        }
        begin=false;
    }
    return result.toString();
}

мне пришлось реализовать это, чтобы преобразовать некоторые ключи в формате camel case в нижний регистр с подчеркиванием. Регулярное выражение, которое я придумал:

(?<!^|_|[A-Z])([A-Z])

на английском языке это расшифровывается как заглавная буква, которой не предшествует начало строки, подчеркивание или другая заглавная буква.

в приведенных ниже примерах жирным шрифтом выделены символы, которые должны привести к совпадению с использованием вышеупомянутого регулярного выражение:

  • верблюдCaseToS omethingElse
  • верблюдCaseToS omethingElse
  • camel_case_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

обратите внимание, что выражение не влияет на строку, которая уже находится в нижнем регистре + формат подчеркивания.

шаблон замены будут:

_l

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