0

の最近の使用ではString.split()、テキストが非常に動的であり、不一致を除外するよりも一致を選択する方が簡単であるという状況に直面しました。

「逆正規表現」を変更して、String.split()任意のパターンを指定でき、そのパターンに一致しないすべての文字グループに一致するようにできるかどうか疑問に思いました。

*注:ここでの「問題」は、、、などで簡単に解決できます。String.matches()この質問はほとんど架空のものであり(質問の性質上、コードサンプルは大歓迎です)、結果を達成する方法についてではありませんが、この方法でそれらを達成することが可能かどうかについて。TokensMatcher.group()


私が試したこと:

String pattern1 = "(test)"; //A verif. that what "should-not-match" is working correctly.
        String pattern2 = "[^(test)]"; //FAIL - unmatches the letters separately.
        String pattern3 = "(^(test))"; //FAIL - does not match anything, it seems.
        String text = ""
                        + "This is a test. "
                        + "This test should (?not?) match the word \"test\", whenever it appears.\n"
                        + "This is about to test if a \"String.split()\" can be used in a different way.\n"
                        + "By the way, \"testing\" does not equal \"test\","
                        + "but it will split in the middle because it contains \"test\".";
        for (String s : text.split(pattern3)) {
            System.out.println(s);
        }

そして、他の同様のパターンは、どれも成功に近いものではありませんでした。


アップデート:

特別なコンストラクターを使用していくつかのパターンを試しましたが、まだ機能しませんでした。

私が欲しいのは、「テスト」の例に従って、内容が「テキスト」(ベースパターンとして使用したいもの、つまり検索したいもの)である文字列を含む配列を取得することです。

ただし、これを使用String.split()して、基本パターンを直接使用すると「(テスト)ではないものは何でも」になるため、「(テスト)の発生だけ」になるように反転する必要があります。

Bible-size-long-story-short、必要なのはString.split()、この動作(+ result)の結果の正規表現です。注:必要な変数(テキスト)を含め、上記のサンプルコードに従います。

String[] trash = text.split("test"); //<-base pattern, needs reversing.
        System.out.println("\n\nWhat should match the split-pattern (due reversal), become separators, and be filtered out:");
        for (String s : trash) {
            System.out.println("[" + s + "]");
            text = text.replace(s, "%!%"); //<-simulated wanted behavior.
        }
        System.out.println("\n\nWhat should be the resulting String[]:");
        for (String s : text.split("%!%")) {
            System.out.println(s);
        }
        System.out.println("Note: There is a blank @ index [0], since if the text does not start with \"test\", there is a sep. between. This is NOT WRONG.");

コードサンプルは大歓迎です。そのようなコードを作成する可能性(または作成しない)は、結局のところ、この質問の性質です。

4

2 に答える 2

3

(?! コンストラクトについて話している可能性があります。

これは、Pattern クラスの javadoc に記載されています。彼らはこれを否定先読みアサーションと呼んでいます。

問題を解決する最も簡単な方法は、検索を繰り返すことです。

    Pattern p = Pattern.compile(regexForThingIWant);
    Matcher m = p.matcher(str);
    int cursor = 0;
    while (m.find(cursor)) {
      String x = m.group();
      // do something with x
      cursor = m.end();
    }

私はあなたが望むことをしているように見える分割の正規表現をこじ開けることができましたが、ひどく:

(^|(?<=test))((?!test).)*
于 2012-07-19T18:02:50.090 に答える
0

唯一のヒントはテスト文字列の一部であり、間接的なものにすぎないため (単語を 2 つに分けて表示しsplitたいなど)、あなたが見たいからの出力を確認するのは簡単ではありません。testing

それでは、肯定的な後読みを試してみましょう。

^|(?<=test)

これは戻ります

This is a test
. This test
 should (?not?) match the word "test
", whenever it appears.
This is about to test
 if a "String.split()" can be used in a different way.
By the way, "test
ing" does not equal "test
",but it will split in the middle because it contains "test
".

それはあなたが望んでいたものですか?

入力の「一致する」ビットと「一致しない」ビットのどちらも (大まかな意味で) 分割プロセスで消費されないようにテキストを分割する場合は、一致するだけになるように正規表現を設計する必要があることに注意してください。 (いくつかの) 空の文字列。「一致」という言葉の技術的な意味で。

したがって、先読みと後読みは、正規表現を使用してそのようなタスクを解決するためのほぼ唯一のツールです。

ただし、テスト以外のすべての部分を消費したい場合は、それも実現可能です。

(?<=^|(test))(tes[^t]|te[^s]|t[^e]|[^t])*

これは、同じ後読みの後に、単語のように見えないものを消費することですtest

ただし、この方法は完全に一般的ではありません。 この質問では、制限について説明しています。

于 2012-07-19T18:35:50.727 に答える