10

重複の可能性:
正規表現に基づいて文字列を分割する

私は正規表現の達人になったことがないので、あなたの助けが必要です! 次のような文字列があります。

String s = "a [b c] d [e f g]";

[]スペースを区切り文字として使用してこの文字列を分割したいのですが、括弧内に表示されるスペースで分割したくありません。したがって、上記の例から、次の配列が必要です。

{"a", "[b c]", "d", "[e f g]"}

splitこれを達成するためにどの正規表現を組み合わせて使用​​できるかについてのアドバイスはありますか?


別の例を次に示します。

"[a b] c [[d e] f g]"

になる

{"[a b]", "c", "[[d e] f g]"}
4

5 に答える 5

10

負の先読みを使用すると、これは機能するはずだと思います-開き括弧なしで閉じ括弧の前にある空白には一致しません:

"a [b c] d [e f g]".split("\\s+(?![^\\[]*\\])");

ネストされたブラケットの場合、パーサーを作成する必要があります。正規表現は無限レベルを許容できず、1 つまたは 2 つのレベルよりも複雑になりすぎます。たとえば、私の式は失敗します

"[a b [c d] e] f g"
于 2012-10-14T17:22:26.457 に答える
4

単一の正規表現でそれを行うことはできません。単純に、開き/閉じ波括弧に一致せず、ネストされた波括弧を処理できないためです。

正規表現はチューリング完全ではないため、機能しているように見えても機能しない場合があります

したがって、すべてのケースを確実に処理する独自の数行のコードをプログラムすることをお勧めします。

JavaCCまたはAntLR用の非常に単純な文法を作成するか、単純なスタックベースのパーサーを使用できます。

于 2012-10-14T17:35:26.613 に答える
3

他の回答で述べたように、そのためにはパーサーが必要です。これは、以前の正規表現ソリューションでは失敗する文字列です。

"[a b] c [a [d e] f g]"

編集:

public static List<String> split(String s){
    List<String> l = new LinkedList<String>();
    int depth=0;
    StringBuilder sb = new StringBuilder();
    for(int i=0; i<s.length(); i++){
        char c = s.charAt(i);
        if(c=='['){
            depth++;
        }else if(c==']'){
            depth--;
        }else if(c==' ' && depth==0){
            l.add(sb.toString());
            sb = new StringBuilder();
            continue;
        }
        sb.append(c);
    }
    l.add(sb.toString());

    return l;
}
于 2012-10-14T17:39:10.737 に答える
0

私があなたの質問を正しく理解していれば、答えはルール 4 に従っている可能性があります。

rule1 -> ((a-z).(\w))*.(a-z)

rule2 -> ([).rule1.(])

rule3 -> ([).(rule1.(\w))*.rule2.((\w).rule1)*.(])

rule4 -> rule1 | rule3
于 2012-10-14T17:21:46.660 に答える
-1

ネストされていない場合

\\s+(?![^\\[]*\\])

FOR NESTED ([] 内 [])

(?<!\\[[^\\]]*)\\s+(?![^\\[]*\\])
于 2012-10-14T17:27:47.297 に答える