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é?
Voir ceci question et CaseFormat
de goyave
dans votre cas, quelque chose comme:
CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");
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());
}
}
Vous pouvez utiliser l'extrait de code ci-dessous:
String replaceAll = key.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase();
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.
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();
}
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.
public class ReplaceFromCameltoSnake {
public static void main(String args[]){
String s1=" totalAmountWithoutDiscount";
String replaceString=s1.replaceAll("([A-Z]+)","\\_$1").toLowerCase();
System.out.println(replaceString);
}
}
([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
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();
}
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:
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.