Eu entendo por que a saída desejada não é fornecida para converter usando regex uma string como FooBar
a Foo_Bar
que em vez disso fornece Foo_Bar_
. Eu poderia ter feito algo com String.substring substring(0, string.length() - 2)
ou apenas substituído o último caractere, mas acho que há uma solução melhor para tal cenário.
Aqui está o 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
*/
Pergunta: Procurando uma maneira mais organizada de obter a saída desejada?
Respostas:
Veja esta pergunta e
CaseFormat
da goiabano seu caso, algo como:
CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");
fonte
vincule a caixa baixa e a caixa alta como dois grupos, vai ficar tudo bem
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()); } }
fonte
IBMIsMyCompany
.Você pode usar o snippet de código abaixo:
String replaceAll = key.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase();
fonte
MyUUID
sublinhado corretamente, entendimy_uu_id
.Não posso fornecer RegEx, seria insanamente complexo de qualquer maneira.
Experimente esta função com reconhecimento automático de siglas.
Infelizmente, Guava lib não detecta automaticamente acrônimos em maiúsculas, então "bigCAT" seria convertido para "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(); }
fonte
Por que não simplesmente combinar o caractere anterior como um não início de linha
$
?String text = "CamelCaseToSomethingElse"; System.out.println(text.replaceAll("([^_A-Z])([A-Z])", "$1_$2"));
Observe que esta versão é segura para ser executada em algo que já está envolto em camelo.
fonte
^
e$
como âncoras? Porque seus significados mudam quando você os coloca em uma classe de personagem.[^$_A-Z]
corresponde a qualquer caractere que não seja$
,_
ou uma letra maiúscula, e não acho que seja isso que você quis dizer.$
foi adicionado por engano, pois é uma técnica que uso em nomes de classes.Adicione uma afirmação antecipada de largura zero.
http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
Leia a documentação para
(?=X)
etc.Pessoalmente, eu iria realmente dividir a string e, em seguida, recombinar. Isso pode até ser mais rápido quando feito da maneira certa e torna o código muito mais fácil de entender do que a mágica de expressão regular. Não me entenda mal: eu adoro expressões regulares. Mas isso não é realmente uma expressão regular puro, nem é esta transformação uma tarefa clássica regexp. Afinal parece que você também quer fazer minúsculas?
Um hack feio, mas rápido, seria substituir
(.)([A-Z]+)
por$1_$2
e depois colocar toda a string em minúsculas (a menos que você possa fazer expressões regulares extrendidas no estilo perl, onde você pode minúsculas a substituição diretamente!). Ainda assim, considero a divisão na transição inferior para superior, a transformação e a união como a maneira adequada e mais legível de fazer isso.fonte
[A-Z][a-z]*
, minúsculas a primeira letra e juntá-los novamente. Ou o truque de substituição + minúsculas que acabei de adicionar à resposta 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); } }
fonte
Não tenho certeza se é possível ter algo realmente sólido com regex puro. Especialmente para apoiar siglas.
Fiz uma pequena função, inspirada na resposta @radzimir, que suporta siglas e nenhum caractere alfabético:
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(); }
fonte
Deve pesquisar uma letra maiúscula seguida de letras minúsculas. O lookahead positivo procurará outra palavra que comece com uma letra maiúscula seguida por letras minúsculas, mas NÃO a incluirá na correspondência.
Olhe aqui: http://regexr.com?30ooo
fonte
Eu tive que implementar isso para converter algumas chaves no formato camel case para minúsculas com sublinhados. A expressão regular que criei é:
(?<!^|_|[A-Z])([A-Z])
Em inglês, significa letra maiúscula que não é precedida pelo início da string, um sublinhado ou outra letra maiúscula .
Nos exemplos abaixo, os caracteres em negrito são os que devem produzir uma correspondência usando a expressão regular mencionada:
Observe que a expressão não afeta a string que já está no formato de minúsculas + sublinhado.
O padrão de substituição seria:
_l$1
O que significa letras minúsculas do primeiro grupo de captura , primeiro o grupo de captura sendo a letra maiúscula. Você também pode colocar a string inteira em letras minúsculas para normalizar as duas últimas amostras da lista acima.
fonte