正则表达式用于在Java中将CamelCase转换为camel_case


86

我明白了为什么使用正则表达式的字符串转换一样没有给出所需的输出FooBarFoo_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
*/

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


Answers:


168

看到这个问题CaseFormat从番石榴

就您而言,类似:

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

@eliocs这个问题没有被标记为android和“更整洁的方式” ..无论如何,谢谢你的downvote;)

2
CaseFormat链接处于脱机状态。更换在这里
Anticom '16

66

将小写和大写绑定为两个组,可以

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
注意:如果输入字符串中允许使用单个字母单词,例如“ thisIsATest”,则上面的代码将打印“ this_is_atest”。番石榴在接受的答案中得出“ this_is_a_test”。
DtotheK '18

这个名称不适用于以大写字母开头的名称,例如:IBMIsMyCompany
User3301

37

您可以使用以下代码段:

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

如果我的字符串包含数字,该怎么办-mode3最终成为mode3,而我想要mode_3。
Mike Stoddart

MyUUID我得到了,它不能正确转换驼峰大小写my_uu_id
User3301

6

我无法提供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();
}

4

为什么不简单地将前面的字符匹配为行首$呢?

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

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


您是否要使用^$作为锚点?因为当您将它们放在字符类中时,它们的含义会发生变化。 [^$_A-Z]匹配不是$_或大写字母的任何字符,但我认为这不是您的意思。
艾伦·摩尔

不打算用作锚,我试图不匹配上位字符,但$由于我在类名上使用的一种技术而被错误添加。
Brett Ryan

3

添加零宽度的超前断言。

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

阅读文档(?=X)等。

就我个人而言,我实际上会拆分字符串,然后重新组合它。如果正确完成,这甚至可能会更快,并且使代码比正则表达式魔术更易于理解。不要误会我的意思:我喜欢正则表达式。但是,这是不是一个真正的整齐的正则表达式,这也不是改造的经典正则表达式任务。毕竟您似乎还想做小写吗?

一个丑陋但快速的黑客将取代(.)([A-Z]+)$1_$2再后来小写整个字符串(除非你可以做到Perl样式extrended正则表达式,在那里你可以直接小写更换!)。我仍然考虑从低到高的过渡进行拆分,然后进行转换,然后再加入,这是正确且最易读的方式。


是的,最终我也希望它也使用小写字母。
ajmartin 2012年

因此,我将其拆分为匹配的块[A-Z][a-z]*,小写第一个字母,然后重新加入。或我刚刚在主要回复中添加的替换小写技巧。
已退出–Anony-Mousse 2012年

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

$ 1用于
组队

2

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

我做了一个小功能,受@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();
}

1
这是一个高质量的答案,它可以处理大多数边缘情况。
User3301

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

应搜索大写字母,后跟小写字母。正向前瞻会寻找另一个单词,该单词以大写字母开头,后跟小写字母,但不会包含在匹配项中。

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


0

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

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

在英语中,它代表大写字母,但不能在字符串开头,下划线或其他大写字母之前

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

  • 骆驼Ç ASE Ť ö小号omething ë LSE
  • 骆驼Ç ASE Ť ö小号omething ë LSE
  • camel_case_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

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

替换模式为:

_l$1

这意味着一个捕获组的小写字母,第一个捕获组是大写字母。之后,您还可以小写整个字符串,以标准化上面列表中的最后两个样本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.