JavaでCamelCaseをcamel_caseに変換するための正規表現


86

正規表現を使用して変換するために必要な出力が与えられない理由を理解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
*/

質問:目的の出力を取得するためのより適切な方法をお探しですか?


回答:


168

この質問CaseFormatグアバから

あなたの場合、次のようなものです。

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

@eliocs質問はアンドロイドと「きちんとした方法」のタグが付けられていませんでした..とにかく反対票をありがとう;)

2
CaseFormatリンクはオフラインです。交換はこちら
Anticom 2016年

66

小文字と大文字を2つのグループとしてバインドします。問題ありません。

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」のように、入力文字列で1文字の単語が許可されている場合、上記のコードは「this_is_atest」を出力します。受け入れられた回答では、グアバは「this_is_a_test」になります。
DtotheK

これは、大文字で始まる名前では機能しませんIBMIsMyCompany。例:。
User3301

37

以下のコードスニペットを使用できます。

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

文字列に数値が含まれている場合はどうなりますか?mode3はmode3になりますが、mode_3が必要です。
マイクストッダート2017

キャメルケースMyUUIDを適切に強調するように変換しません、私は得ましたmy_uu_id
User3301

6

正規表現を提供することはできません。とにかくめちゃくちゃ複雑になります。

頭字語の自動認識でこの機能を試してください。

残念ながら、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]ない任意の文字と一致し$_または大文字を、そして私はあなたが何を意味するかだとは思いません。
アランムーア

アンカーとして意図せず、上位文字と一致させようとしてい$ますが、クラス名で使用する手法であるため、誤って追加されました。
ブレットライアン

3

ゼロ幅の先読みアサーションを追加します。

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

(?=X)などのドキュメントをお読みください。

個人的には、実際に文字列を分割してから再結合します。これは、正しく実行するとさらに高速になる可能性があり、正規表現の魔法よりもコードをはるかに理解しやすくなります。誤解しないでください。正規表現が大好きです。しかし、これは実際にはきちんとした正規表現ではなく、この変換は古典的な正規表現タスクでもありません。結局のところ、小文字もやりたいようですか?

醜いが迅速なハックは、文字列全体を置き換え(.)([A-Z]+)$1_$2から小文字にすることです(置換を直接小文字にできるperlスタイルの拡張正規表現を実行できる場合を除く)。それでも私は、これを行うための適切で最も読みやすい方法として、下位から上位への遷移で分割し、次に変換し、次に結合することを検討しています。


はい、最終的には小文字にもしたいと思います。
ajmartin 2012

だから私はそれを一致するチャンクに分割し[A-Z][a-z]*、最初の文字を小文字にして、それらを再結合します。または、メインの返信に追加した置換+小文字のトリック。
-匿名-ムース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-グループの作成に使用
abinash sahu 2016

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])

英語では、文字列の先頭、アンダースコア、または別の大文字が前に付いていない大文字を表します。

以下のサンプルでは、​​太字の文字は、前述の正規表現を使用して一致を生成する必要がある文字です。

  • ラクダC ASE T O S omething EのLSE
  • ラクダC ASE T O S omething EのLSE
  • キャメルケース_to_something_else
  • Camel_Case_To_Something_Else
  • CAMEL_CASE_TO_SOMETHING_ELSE

式は、すでに小文字+アンダースコア形式になっている文字列には影響しないことに注意してください。

置換パターンは次のようになります。

_l$1

つまり、最初のキャプチャグループ小文字で、最初のキャプチャグループは大文字です。後で文字列全体を小文字にして、上記のリストの最後の2つのサンプルを正規化することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.