Entiendo por qué la salida deseada no se le da el uso de expresiones regulares para convertir una cadena como FooBar
a Foo_Bar
que da lugar Foo_Bar_
. Podría haber hecho algo con String.substring substring(0, string.length() - 2)
o simplemente reemplazar el último carácter, pero creo que hay una mejor solución para tal escenario.
Aquí está el código:
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
*/
Pregunta: ¿Busca una forma más ordenada de obtener el resultado deseado?
Respuestas:
Ver esta pregunta y
CaseFormat
de guayabaen tu caso, algo como:
CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");
fuente
enlazar la minúscula y la mayúscula como dos grupos, estará 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()); } }
fuente
IBMIsMyCompany
.Puede utilizar el siguiente fragmento de código:
String replaceAll = key.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase();
fuente
MyUUID
subrayado correctamente, lo tengomy_uu_id
.No puedo proporcionar RegEx, sería increíblemente complejo de todos modos.
Pruebe esta función con reconocimiento automático de siglas.
Desafortunadamente, Guava lib no detecta automáticamente los acrónimos en mayúsculas, por lo que "bigCAT" se convertiría 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(); }
fuente
¿Por qué no simplemente hacer coincidir el carácter anterior como un no comienzo de línea
$
?String text = "CamelCaseToSomethingElse"; System.out.println(text.replaceAll("([^_A-Z])([A-Z])", "$1_$2"));
Tenga en cuenta que esta versión es segura para realizar en algo que ya está en caja de camello.
fuente
^
y$
como anclajes? Porque sus significados cambian cuando los colocas en una clase de personaje.[^$_A-Z]
coincide con cualquier carácter que no sea$
,_
o una letra mayúscula, y no creo que eso sea lo que quisiste decir.$
se agregó por error ya que es una técnica que uso en los nombres de clase.Agregue una aserción de anticipación de ancho cero.
http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
Lea la documentación para
(?=X)
etc.Personalmente, dividiría la cadena y luego la recombinaría. Esto puede ser incluso más rápido cuando se hace correctamente, y hace que el código sea mucho más fácil de entender que la magia de las expresiones regulares. No me malinterpretes: me encantan las expresiones regulares. Pero esta no es realmente una expresión regular ordenada, ni esta transformación una tarea clásica de . ¿Después de todo parece que también quieres hacerlo en minúsculas?
Un truco feo, pero rápida sería la de sustituir
(.)([A-Z]+)
con$1_$2
y minúsculas toda la cadena después (a menos que puede hacer las expresiones regulares de Perl estilo extrended, donde se puede minúsculas la sustitución directa!). Aún así, considero dividir en la transición de abajo hacia arriba, luego transformar y luego unir como la forma adecuada y más legible de hacer esto.fuente
[A-Z][a-z]*
, en minúscula la primera letra y volver a unirlos. O el truco de reemplazo + minúsculas que acabo de agregar a la respuesta principal.public class ReplaceFromCameltoSnake { public static void main(String args[]){ String s1=" totalAmountWithoutDiscount"; String replaceString=s1.replaceAll("([A-Z]+)","\\_$1").toLowerCase(); System.out.println(replaceString); } }
fuente
No estoy seguro de que sea posible tener algo realmente sólido con expresiones regulares puras. Especialmente para apoyar acrónimos.
Hice una pequeña función, inspirada en la respuesta de @radzimir, que admite acrónimos y no caracteres alfabéticos:
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(); }
fuente
Debe buscar una letra mayúscula seguida de letras minúsculas. La búsqueda anticipada positiva buscará otra palabra que comience con una letra mayúscula seguida de letras minúsculas, pero NO la incluirá en la coincidencia.
Mira aquí: http://regexr.com?30ooo
fuente
Tuve que implementar esto para convertir algunas claves en formato camel a minúsculas con guiones bajos. La expresión regular que se me ocurrió es:
(?<!^|_|[A-Z])([A-Z])
En inglés, significa letra mayúscula que no está precedida por el comienzo de la cadena, un guión bajo u otra letra mayúscula .
En los ejemplos a continuación, los caracteres en negrita son los que deberían producir una coincidencia usando la expresión regular mencionada anteriormente:
Observe que la expresión no afecta a las cadenas que ya están en formato de minúsculas + subrayado.
El patrón de reemplazo sería:
_l$1
Lo que significa minúscula del primer grupo de captura, siendo el primer grupo de captura la letra mayúscula. También puede minúscula toda la cadena después para normalizar las dos últimas muestras de la lista anterior.
fuente