web-dev-qa-db-fra.com

Regex pour convertir CamelCase en camel_case dans java

Je comprends pourquoi la sortie souhaitée n’est pas donnée pour la conversion utilisant regex une chaîne comme FooBar en Foo_Bar, Ce qui donne Foo_Bar_. J'aurais pu faire quelque chose avec String.substring substring(0, string.length() - 2) ou simplement remplacer le dernier caractère, mais je pense qu'il existe une meilleure solution à un tel scénario.

Voici le code:

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
*/

Question: Vous cherchez un moyen plus ordonné d'obtenir le résultat souhaité?

70
ajmartin

Voir ceci question et CaseFormat de goyave

dans votre cas, quelque chose comme:

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

lier les minuscules et les majuscules en deux groupes, tout ira bien

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());
    }
}
57
clevertension

Vous pouvez utiliser l'extrait de code ci-dessous:

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

Pourquoi ne pas simplement faire correspondre le caractère précédent au début de la ligne $?

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

Notez que cette version est sans danger pour être effectuée sur quelque chose qui est déjà chamelée.

5
Brett Ryan

Je ne peux pas fournir de RegEx, ce serait incroyablement complexe de toute façon.

Essayez cette fonction avec la reconnaissance automatique des acronymes.

Malheureusement, Guava lib ne détecte pas automatiquement les acronymes en majuscules, donc "bigCAT" serait converti en "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();
}
3
radzimir

Ajouter une assertion lookahead de largeur zéro.

http://docs.Oracle.com/javase/6/docs/api/Java/util/regex/Pattern.html

Lisez la documentation pour (?=X) etc.

Personnellement, je voudrais scinder la chaîne, puis la recombiner. Cela peut même être plus rapide si c'est bien fait, et cela rend le code beaucoup plus facile à comprendre que la magie des expressions régulières. Ne vous méprenez pas: j'adore les expressions régulières. Mais ce n'est pas vraiment une expression régulière soignée, ni cette transformation une tâche regexp classique. Après tout, il semble que vous souhaitiez aussi faire des minuscules?

Un hack rapide mais rapide serait de remplacer (.)([A-Z]+) avec $1_$2 puis en minuscule toute la chaîne par la suite (à moins que vous ne puissiez créer des expressions rationnelles extraites à la Perl, où vous pouvez directement remplacer le remplacement en minuscule!). Néanmoins, je considère que scinder à la transition inférieure-supérieure, puis de transformer, puis de rejoindre, est le moyen le plus approprié et le plus lisible de le faire.

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

Devrait rechercher une lettre majuscule suivie de lettres minuscules. Le témoin positif recherchera un autre mot commençant par une lettre majuscule suivie de lettres minuscules, mais ne l'inclura PAS dans la correspondance.

Regardez ici: http://regexr.com?30ooo

1
Jack

Pas sûr qu'il soit possible d'avoir quelque chose de vraiment solide avec une regex pure. Surtout pour supporter les acronymes.

J'ai créé une petite fonction, inspirée de @radzimir answer, qui prend en charge les acronymes et aucun caractère alphabétique:

De 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();
}
0
Thomas Decaux

J'ai dû implémenter ceci pour convertir certaines clés au format cas et camel en minuscules avec des traits de soulignement. L'expression régulière que j'ai créée est la suivante:

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

En anglais, il s'agit de lettre majuscule qui n'est pas précédée du début de la chaîne, d'un trait de soulignement ou d'une autre lettre majuscule .

Dans les exemples ci-dessous, les caractères en gras sont ceux qui doivent produire une correspondance en utilisant l'expression régulière susmentionnée:

  • Chameau C ase T o S omething E lse
  • chameau C ase T o S omething E lse
  • camel_case_to_something_else
  • Camel_Case_To_Quelque chose_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

Notez que l'expression n'affecte pas les chaînes déjà au format minuscule + trait de soulignement.

Le modèle de remplacement serait:

_l$1

Ce qui signifie minuscule le premier groupe de capture , le premier groupe de capture étant la lettre majuscule. Vous pouvez ensuite mettre la chaîne entière en minuscule pour normaliser les deux derniers échantillons de la liste ci-dessus.

0
argenkiwi