99

我理解为什么没有给出所需的输出来使用正则表达式转换一个字符串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
*/

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

4

13 回答 13

189

看到这个问题CaseFormat番石榴

在您的情况下,例如:

CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "SomeInput");
于 2012-04-25T06:23:58.927 回答
71

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

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());
    }
}
于 2012-04-25T06:44:18.063 回答
43

您可以使用以下代码片段:

String replaceAll = key.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase();
于 2013-08-12T18:54:26.220 回答
7

我不能提供正则表达式,反正它会非常复杂。

尝试使用自动识别首字母缩略词的功能。

不幸的是,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();
}
于 2018-06-13T12:56:51.237 回答
5

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

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

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

于 2014-10-14T10:36:50.753 回答
3

添加一个零宽度的前瞻断言。

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

阅读文档(?=X)等。

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

一个丑陋但快速的技巧是替换(.)([A-Z]+)整个$1_$2字符串,然后再小写整个字符串(除非你可以做 perl 风格的扩展正则表达式,你可以直接小写替换!)。我仍然考虑在从下到上的过渡中拆分,然后转换,然后加入作为这样做的正确和最易读的方式。

于 2012-04-25T06:21:03.217 回答
3

不确定是否有可能使用纯正则表达式真正巩固一些东西。特别是支持首字母缩略词。

我做了一个小函数,受@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();
}
于 2019-08-23T19:30:01.117 回答
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);  
    }
}
于 2016-08-21T17:07:18.913 回答
1
([A-Z][a-z\d]+)(?=([A-Z][a-z\d]+))

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

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

于 2012-04-25T06:29:40.897 回答
1

如果有人出于任何原因不想使用 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;
    }
}
于 2021-02-03T23:38:56.700 回答
0

我必须实现它以将驼峰格式的一些键转换为带下划线的小写。我想出的正则表达式是:

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

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

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

  • Camel Case T o S something Else _ _
  • 骆驼案T o S something Else _ _
  • camel_case_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

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

替换模式将是:

_l$1

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

于 2018-09-06T02:38:38.690 回答
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
于 2021-04-17T05:03:20.140 回答
0

您可以使用 Java 8 中的 Stream API 和commons-lang中的方法StringUtils.capitalize(..)轻松地将 String 转换为驼峰式大小写

 public String toCamelCase(String str) {
    return Arrays.stream(str.split("_"))
        .map(StringUtils::capitalize)
        .collect(Collectors.joining());
}
于 2022-01-21T12:12:09.750 回答