Regex for converting CamelCase to camel_case in java

JavaRegexString

Java Problem Overview


I understand why the desired output is not given for converting using regex a string like FooBar to Foo_Bar which instead gives Foo_Bar_. I could have done something with String.substring substring(0, string.length() - 2) or just replaced the last character, but I think there is a better solution to such a scenario.

Here is the 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: Looking for a neater way to get the desired output?

Java Solutions


Solution 1 - Java

See this question and CaseFormat from guava

in your case, something like:

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

Solution 2 - Java

bind the lower case and upper case as two group,it will be ok

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

Solution 3 - Java

You can use below code snippet:

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

Solution 4 - Java

I can't provide RegEx, it would be insanely complex anyway.

Try this function with automatic recognition of acronyms.

Unfortunately Guava lib doesn't auto detect upper case acronyms, so "bigCAT" would be converted to "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();
}

Solution 5 - Java

Why not simply match prior character as a not start of line $?

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

Note that this version is safe to be performed on something that is already camel cased.

Solution 6 - Java

Add a zero-width lookahead assertion.

http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html

Read the documentation for (?=X) etc.

Personally, I would actually split the string, then recombine it. This may even be faster when done right, and it makes the code much easier to understand than regular expression magic. Don't get me wrong: I love regular expressions. But this isn't really a neat regular expression, nor is this transformation a classic regexp task. After all it seems you also want to do lowercase?

An ugly but quick hack would be to replace (.)([A-Z]+) with $1_$2 and then lowercase the whole string afterwards (unless you can do perl-style extrended regexps, where you can lowercase the replacement directly!). Still I consider splitting at lower-to-upper transition, then transforming, then joining as the proper and most readable way of doing this.

Solution 7 - Java

Not sure it's possible to have something really solide with pure regex. Especially to support acronyms.

I have made a small function, inspired by @radzimir answer, that supports acronyms and no alphabetic character:

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

Solution 8 - Java

public class ReplaceFromCameltoSnake {
    public static void main(String args[]){
	    String s1=" totalAmountWithoutDiscount";  
	    String replaceString=s1.replaceAll("([A-Z]+)","\\_$1").toLowerCase(); 
	    System.out.println(replaceString);  
	}
}

Solution 9 - Java

([A-Z][a-z\d]+)(?=([A-Z][a-z\d]+))

Should search for a capital letter followed by lowercase letters. The positive lookahead will look for another word starting with a capital letter followed by lowercase letters but will NOT include it in the match.

Look here: http://regexr.com?30ooo

Solution 10 - Java

I am writing this answer if somebody doesn't want to use Guava as below for any reason.

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

In our case we had problem with storage. There is another special case with Guava: if we have "Ph_D" as input, then we are going to get "ph__d" with two underscores.

The code below worked as long as I tested it.

public static String camelCaseToLowerCaseWithUnderscore(String string) {
    if (string.matches(".*[a-z].*")) {
        final Matcher matcher = Pattern.compile("(_?[A-Z][a-z]?)").matcher(string);

        StringBuffer stringBuffer = new StringBuffer();
        matcher.find(); // This is just to escape the first group (beginning of string)
        while (matcher.find()) {
            final String group = matcher.group();
            if (!group.startsWith("_")) {
                matcher.appendReplacement(stringBuffer, "_" + group);
            }
        }
        matcher.appendTail(stringBuffer);
        return stringBuffer.toString().toLowerCase();
    }
    else {
        return string;
    }
}

Solution 11 - Java

I've had to implement this to convert some keys in camel case format to lower case with underscores. The regular expression I came up with is:

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

In english it stands for capital letter which is not preceded by the start of the string, an underscore or another capital letter.

In the samples below, the character in bold are the ones that should produce a match using the aforementioned regular expression:

  • CamelCaseToSomethingElse
  • camelCaseToSomethingElse
  • camel_case_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

Notice the expression does not affect string that are already in lower case + underscore format.

The replacement pattern would be:

_l$1

Which means lower case of first capturing group, first capturing group being the capital letter. You could lower case the whole string afterwards as well to normalize the last two samples from the list above.

Solution 12 - Java

Here my solution with 3 regular expression:

str.replaceAll("([^A-Z])([A-Z0-9])", "$1_$2") // standard replace
                   .replaceAll("([A-Z]+)([A-Z0-9][^A-Z]+)", "$1_$2") // last letter after full uppercase.
                    .replaceAll("([0-9]+)([a-zA-Z]+)", "$1_$2").toLowerCase(); // letters after numbers

The result:

thisIsATest: this_is_a_test
EndWithNumber3: end_with_number_3
3ThisStartWithNumber: 3_this_start_with_number
Number3InMiddle: number_3_in_middle
Number3inMiddleAgain: number_3_in_middle_again
MyUUIDNot: my_uuid_not
HOLAMundo: hola_mundo
holaMUNDO: hola_mundo
with_underscore: with_underscore
withAUniqueLetter: with_a_unique_letter

Solution 13 - Java

You can easily convert String to camel case using Stream API from Java 8 and method StringUtils.capitalize(..) from commons-lang

 public String toCamelCase(String str) {
    return Arrays.stream(str.split("_"))
        .map(StringUtils::capitalize)
        .collect(Collectors.joining());
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionajmartinView Question on Stackoverflow
Solution 1 - Javauser180100View Answer on Stackoverflow
Solution 2 - JavaclevertensionView Answer on Stackoverflow
Solution 3 - JavaSandeep VaidView Answer on Stackoverflow
Solution 4 - JavaradzimirView Answer on Stackoverflow
Solution 5 - JavaBrett RyanView Answer on Stackoverflow
Solution 6 - JavaHas QUIT--Anony-MousseView Answer on Stackoverflow
Solution 7 - JavaThomas DecauxView Answer on Stackoverflow
Solution 8 - Javaabinash sahuView Answer on Stackoverflow
Solution 9 - JavaJackView Answer on Stackoverflow
Solution 10 - JavaGovanView Answer on Stackoverflow
Solution 11 - JavaargenkiwiView Answer on Stackoverflow
Solution 12 - JavaAliView Answer on Stackoverflow
Solution 13 - JavaVolodymyr DvornykView Answer on Stackoverflow