Java'da CamelCase'i camel_case'e dönüştürmek için normal ifade


86

İstenen çıkış gibi bir dize regex kullanarak dönüştürmek için verilmez anlıyorum FooBariçin Foo_Baryerine veren Foo_Bar_. String.substring ile bir şeyler yapabilirdim substring(0, string.length() - 2)veya son karakteri değiştirebilirdim, ancak böyle bir senaryo için daha iyi bir çözüm olduğunu düşünüyorum.

İşte kod:

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

"CamelCaseToSomethingElse".replaceAll(regex, replacement); 

/*
outputs: Camel_Case_To_Something_Else_
desired output: Camel_Case_To_Something_Else
*/

Soru: İstenilen çıktıyı elde etmenin daha düzgün bir yolunu mu arıyorsunuz?


Yanıtlar:


171

Bu soruyu ve CaseFormatguava'dan bakın

senin durumunda şöyle bir şey:

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

@eliocs soru android ve "düzgün bir şekilde" etiketlenmedi .. Yine de olumsuz oy için teşekkürler;)

2
CaseFormat bağlantısı çevrimdışı. Değişim burada
Anticom

66

küçük ve büyük harfleri iki grup olarak bağlayın, tamam olacak

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

2
Not: Giriş String'de tek harfli kelimelere izin veriliyorsa, örneğin "thisIsATest", yukarıdaki kod "this_is_atest" yazacaktır. Guava, kabul edilen cevapta "this_is_a_test" ile sonuçlanır.
DtotheK

Bu bir isim değil iş örn kapaklar, ile başlayacak: IBMIsMyCompany.
Kullanıcı3301

37

Aşağıdaki kod parçasını kullanabilirsiniz:

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

Ya benim dizem bir sayı içeriyorsa - mode3 mod3 olarak bitiyor, oysa ben mode_3 istiyorsam.
Mike Stoddart

Doğru MyUUIDşekilde altını çizmek gibi deve durumunu dönüştürmüyor , anladım my_uu_id.
Kullanıcı3301

6

RegEx'i sağlayamıyorum, yine de delice karmaşık olurdu.

Kısaltmaların otomatik olarak tanınmasıyla bu işlevi deneyin.

Maalesef Guava lib büyük harf kısaltmaları otomatik olarak algılamaz, bu nedenle "bigCAT" "BIG_C_A_T" olarak dönüştürülür.

/**
 * 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();
}

5

Neden sadece önceki karakterle satırın başlangıcı olarak eşleşmiyor $?

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

Bu versiyonun halihazırda deve kasalı olan bir şey üzerinde uygulanmasının güvenli olduğunu unutmayın.


Kullanmak çalışıyorsunuz ^ve $çapa olarak? Çünkü onları bir karakter sınıfına koyduğunuzda anlamları değişir. [^$_A-Z]olmayan herhangi bir karakterle eşleşir $, _veya bir büyük harf ve bunun ne anlama geldiğini sanmıyorum.
Alan Moore

Çapa olarak niyet etmiyorum, Üst karakterle eşleşmemeye çalışıyorum $, sınıf isimlerinde kullandığım bir teknik olduğu için yanlışlıkla eklendi.
Brett Ryan

3

Sıfır genişlikli bir önden okuma iddiası ekleyin.

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

(?=X)Vb . İçin belgeleri okuyun .

Şahsen, aslında ipi böler ve sonra yeniden birleştirirdim. Bu, doğru yapıldığında daha da hızlı olabilir ve kodu, normal ifade sihrinden çok daha kolay anlaşılır hale getirir. Beni yanlış anlamayın: Normal ifadeleri seviyorum. Ancak bu gerçekten düzgün bir düzenli ifade değil, bu dönüşüm de klasik bir düzenli ifade görevi değil. Ne de olsa küçük harf yapmak da istiyorsun.

Çirkin ama çabuk kesmek yerine olacaktır (.)([A-Z]+)ile $1_$2ve sonrasında tüm dizeyi küçük harfe (Eğer doğrudan değiştirme küçük harfe olabilir perl tarzı extrended İfadelerinin, yapabileceği sürece!). Yine de aşağıdan yukarıya geçişte bölmeyi, sonra dönüştürmeyi, sonra bunu yapmanın en uygun ve okunabilir yolu olarak katılmayı düşünüyorum.


Evet, sonunda ben de küçük harf olmasını isterim.
ajmartin

Bu yüzden onu eşleşen parçalara böler [A-Z][a-z]*, ilk harfi küçük harfle yazar ve yeniden birleştirirdim. Veya ana yanıta yeni eklediğim değiştirme + küçük harf numarası.
ÇIKTI - Anony-Mousse

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

1 $
-grup

2

Saf normal ifadeyle gerçekten sağlam bir şeye sahip olmanın mümkün olduğundan emin değilim. Özellikle kısaltmaları desteklemek için.

Kısaltmaları destekleyen ve alfabetik karakter içermeyen, @radzimir cevabından esinlenerek küçük bir işlev yaptım:

Gönderen https://gist.github.com/ebuildy/cf46a09b1ac43eea17c7621b7617ebcd :

private static String snakeCaseFormat(String name) {
    final StringBuilder result = new StringBuilder();

    boolean lastUppercase = false;

    for (int i = 0; i < name.length(); i++) {
        char ch = name.charAt(i);
        char lastEntry = i == 0 ? 'X' : result.charAt(result.length() - 1);
        if (ch == ' ' || ch == '_' || ch == '-' || ch == '.') {
            lastUppercase = false;

            if (lastEntry == '_') {
                continue;
            } else {
                ch = '_';
            }
        } else if (Character.isUpperCase(ch)) {
            ch = Character.toLowerCase(ch);
            // is start?
            if (i > 0) {
                if (lastUppercase) {
                    // test if end of acronym
                    if (i + 1 < name.length()) {
                        char next = name.charAt(i + 1);
                        if (!Character.isUpperCase(next) && Character.isAlphabetic(next)) {
                            // end of acronym
                            if (lastEntry != '_') {
                                result.append('_');
                            }
                        }
                    }
                } else {
                    // last was lowercase, insert _
                    if (lastEntry != '_') {
                        result.append('_');
                    }
                }
            }
            lastUppercase = true;
        } else {
            lastUppercase = false;
        }

        result.append(ch);
    }
    return result.toString();
}

1
Bu kaliteli bir cevaptır, en uç durumların çoğunu ele alır.
Kullanıcı3301

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

Büyük harf ve ardından küçük harf aramalı. Olumlu bakış açısı, büyük harfle başlayan ve ardından küçük harflerle başlayan başka bir kelime arayacak, ancak eşleşmeye dahil edilmeyecektir.

Buraya bakın: http://regexr.com?30ooo


0

Bunu deve harf biçimindeki bazı anahtarları alt çizgi ile küçük harfe dönüştürmek için uygulamak zorunda kaldım. Bulduğum normal ifade:

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

İngilizcede dizenin başlangıcından önce olmayan büyük harf, alt çizgi veya başka bir büyük harf anlamına gelir .

Aşağıdaki örneklerde, kalın karakter, yukarıda belirtilen normal ifadeyi kullanarak bir eşleşme oluşturması gereken karakterlerdir:

  • Deve ase T O S omething e LSE
  • deve ase T O S omething e LSE
  • camel_case_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

İfadenin zaten küçük harf + alt çizgi biçiminde olan dizeyi etkilemediğine dikkat edin.

Değiştirme modeli şöyle olacaktır:

_l$1

Bu , ilk yakalama grubunun küçük harf, ilk yakalama grubunun büyük harf olduğu anlamına gelir . Yukarıdaki listeden son iki örneği normalleştirmek için daha sonra tüm dizeyi küçültebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.