Ответ 1
Смотрите этот вопрос и CaseFormat
из гуавы
в вашем случае что-то вроде:
CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");
Я понимаю, почему желаемый результат не задан для преобразования с использованием regex строки типа FooBar
в Foo_Bar
, которая вместо этого дает Foo_Bar_
. Я мог бы что-то сделать с String.substring substring(0, string.length() - 2)
или просто заменить последний символ, но я думаю, что есть лучшее решение для такого сценария.
Вот код:
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
*/
Вопрос: Ищете более простой способ получить желаемый результат?
Смотрите этот вопрос и CaseFormat
из гуавы
в вашем случае что-то вроде:
CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");
свяжите нижний регистр и верхний регистр как две группы, это будет нормально
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());
}
}
Вы можете использовать ниже фрагмент кода:
String replaceAll = key.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase();
Почему бы просто не совместить предшествующий символ как не начало строки $
?
String text = "CamelCaseToSomethingElse";
System.out.println(text.replaceAll("([^_A-Z])([A-Z])", "$1_$2"));
Обратите внимание, что эта версия безопасна для выполнения чего-то, что уже с верблюдом.
Добавить утверждение с нулевой шириной.
http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
Прочитайте документацию для (?=X)
и т.д.
Лично я бы на самом деле разделил строку, а затем рекомбинировал ее. Это может быть даже быстрее, когда это делается правильно, и это делает код намного понятнее, чем магия регулярного выражения. Не поймите меня неправильно: я люблю регулярные выражения. Но это не очень аккуратное регулярное выражение, и это преобразование не является классической задачей регулярного выражения. В конце концов, кажется, вы также хотите сделать строчные буквы?
Уродливым, но быстрым взломом было бы заменить (.)([A-Z]+)
на $1_$2
, а затем записать нижнюю строчку всей строки (если только вы не можете использовать расширенные регулярные выражения в стиле perl, где вы можете напрямую спрятать замену!). Тем не менее, я рассматриваю расщепление при переходе от нижнего к верхнему, а затем преобразование, а затем соединение как правильный и наиболее читаемый способ сделать это.
Я не могу предоставить RegEx, это было бы безумно сложно в любом случае.
Попробуйте эту функцию с автоматическим распознаванием сокращений.
К сожалению, библиотека Guava не может автоматически определять прописные буквы, поэтому "bigCAT" будет преобразован в "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();
}
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]+))
Должен искать заглавную букву, за которой следуют строчные буквы. Позитивный взгляд будет искать другое слово, начинающееся с заглавной буквы, за которой следуют строчные буквы, но НЕ будет включать его в матч.
Посмотрите здесь: http://regexr.com?30ooo
Мне пришлось реализовать это, чтобы преобразовать некоторые ключи в верблюжьем формате в нижний регистр с подчеркиванием. Регулярное выражение, которое я придумал:
(?<!^|_|[AZ])([AZ])
В английском это означает заглавную букву, которой не предшествует начало строки, подчеркивание или другая заглавная буква.
В приведенных ниже примерах жирным шрифтом обозначены те символы, которые должны соответствовать, используя вышеупомянутое регулярное выражение:
Обратите внимание, что выражение не влияет на строку, которая уже в нижнем регистре + символ подчеркивания.
Шаблон замены будет:
_l$1
Что означает строчную букву первой группы захвата, причем первая группа захвата является заглавной буквой. Впоследствии вы также можете записать всю строку в нижнем регистре, чтобы нормализовать последние два образца из списка выше.
Не уверен, что можно получить что-то действительно с чистым регулярным выражением. Особенно в поддержку аббревиатур.
Я сделал небольшую функцию, вдохновленную ответом @radzimir, которая поддерживает аббревиатуры и не содержит буквенных символов:
С 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();
}