用于将CamelCase转换为java中的camel_case的正则表达式

时间:2012-04-25 06:17:59

标签: java regex string

我理解为什么没有给出使用正则表达式将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
*/

问题:寻找更简洁的方法来获得所需的输出?

12 个答案:

答案 0 :(得分:133)

请参阅此questionCaseFormat from guava

在你的情况下,例如:

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

答案 1 :(得分:56)

将小写和大写绑定为两组,这样就可以了

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

答案 2 :(得分:34)

您可以使用以下代码段:

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

答案 3 :(得分:4)

为什么不简单地将先前字符作为行$的不开头?

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

请注意,此版本可以安全地在已经骆驼的东西上执行。

答案 4 :(得分:3)

添加零宽度前瞻断言。

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

阅读(?=X)等文档

就个人而言,我实际上拆分字符串,然后重新组合它。如果做得好,这甚至可能更快,并且它使代码比正则表达式魔术更容易理解。不要误会我的意思:我喜欢正则表达式。但这并不是一个简洁的正则表达式,这个转换也不是一个经典的正则表达式任务。毕竟你似乎也想做小写?

一个丑陋但快速的黑客攻击是将(.)([A-Z]+)替换为$1_$2,然后将整个字符串小写(除非你可以使用perl风格的extrended regexp,你可以直接小写替换!) 。我仍然考虑在从低到高的转换中进行拆分,然后进行转换,然后将其作为正确且最易读的方式加入。

答案 5 :(得分:2)

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

答案 6 :(得分:2)

我无法提供RegEx,无论如何它都会非常复杂。

尝试此功能并自动识别首字母缩略词。

不幸的是,Guava lib并没有自动检测大写的首字母缩略词,所以" 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();
}

答案 7 :(得分:1)

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

应该搜索大写字母后跟小写字母。积极的向前看将寻找另一个单词,以大写字母开头,后跟小写字母,但不会在匹配中包含它。

请看这里:http://regexr.com?30ooo

答案 8 :(得分:0)

我必须实现此功能才能将驼峰格式的某些键转换为带下划线的小写字母。我想出的正则表达式是:

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

在英语中,它代表大写字母,其后没有字符串开头,下划线或其他大写字母

在以下示例中,粗体字符是应该使用上述正则表达式进行匹配的字符:

  • Camel C ase T o S 其他事物 E 其他
  • camel C ase T o S 其他事物 E 其他
  • camel_case_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

请注意,该表达式不会影响已经为小写+下划线格式的字符串。

替换模式为:

_l$1

这表示第一个捕获组的小写,第一个捕获组是大写字母。您还可以在之后对整个字符串进行小写,以规范化上面列表中的最后两个样本。

答案 9 :(得分:0)

不确定使用纯正则表达式确实可以使某些东西牢固。尤其是支持首字母缩写词。

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

答案 10 :(得分:0)

如果有人出于任何原因不想如下使用 Guava,我正在写这个答案。

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

在我们的案例中,我们遇到了存储问题。 Guava 还有一个特殊情况:如果我们有“Ph_D”作为输入,那么我们将得到带有两个下划线的“ph__d”。

只要我测试过,下面的代码就可以工作。

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

答案 11 :(得分:0)

这是我使用 3 个正则表达式的解决方案:

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

结果:

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