4

Javaと正規表現を使用しており、一部のデータを複数のエンティティに分割する必要があります。私の入力では、一重引用符(')は、疑問符(?)であるエスケープ文字が前に付いていない限り、エンティティの終わりを指定します。

私の正規表現は(?<!\\?)\\' 、スキャナーを使用して入力を個別のエンティティに分割しています。したがって、次の場合は正しく機能します。

Hello'There  becomes 2 entities: Hello and There
Hello?'There remains 1 entity:   Hello?'There

ただし、疑問符をエスケープしたい場合は機能しません。それで:

Hello??'There     should become 2 entities:   Hello?? and There
Hello???'There    should become 1 entity:     Hello???'There
Hello????'There   should become 2 entities:   Hello???? and There
Hello?????'There  should become 1 entity:     Hello????'There
Hello?????There   should become 1 entity:     Hello????There
Hello??????There  should become 1 entity:     Hello?????There

したがって、ルールは、疑問符の数が偶数で、その後に引用符が続く場合は、分割する必要があります。疑問符の数が奇数の場合は、分割しないでください。

誰かが私の正規表現を修正して(うまくいけば説明付きで!)複数のケースに対処するのを手伝ってもらえますか?

ありがとう、

フィル

4

3 に答える 3

3

次の場合でも一致するようにこの式を試してください。(?<=[^\?](?>\?\?){0,1000})'

  • (?<=...)'はポジティブな見た目です。つまり、と'の間の式が前に付いているものはすべて一致します。(?<=)
  • (?>\?\?)2つの連続する疑問符のアトミックグループです
  • (?>\?\?){0,1000}これらのグループは0〜1000個存在する可能性があることを意味します。(?>\?\?)*式には最大長(グループの最大数)が必要なため、記述できないことに注意してください。ただし、式の残りの部分に応じて、上限を大幅に増やすことができるはずです。
  • [^\?](?>\?\?)...つまり、2つの疑問符のグループの前には疑問符を付けないでください(そうでない場合は、奇妙なケースに一致します)。
于 2012-09-07T11:58:14.950 に答える
2

これには使用しないでくださいsplit()。これは明らかな解決策のように見えますが、区切り文字を一致させるよりも、エンティティ自体を一致させる方がはるかに簡単です。findall()PythonやRubyのように、ほとんどの正規表現対応言語にはこのための組み込みメソッドscan()がありますが、Javaではまだボイラープレートの記述に固執しています。次に例を示します。

Pattern p = Pattern.compile("([^?']|\\?.)+");
String[] inputs = {
    "Hello??'There",
    "Hello???'There",
    "Hello????'There",
    "Hello?????'There",
    "Hello?????There",
    "Hello??????There"
};
for (String s : inputs)
{
  System.out.printf("%n%s :%n", s);
  Matcher m = p.matcher(s);
  while (m.find())
  {
    System.out.printf("  %s%n", m.group());
  }
}

出力:

Hello??'There :
  Hello??
  There

Hello???'There :
  Hello???'There

Hello????'There :
  Hello????
  There

Hello?????'There :
  Hello?????'There

Hello?????There :
  Hello?????There

Hello??????There :
  Hello??????There

トーマスが使用した任意の最大長のギミックは、嫌なハックであることに加えて(攻撃は意図されていません、トーマス!)、それらを処理するPattern.javaコードにバグを導入し続けるため、信頼できません。ただし、このソリューションを別の回避策とは考えないでください。ルックビハインドは、信頼性が高く制限のない.NETのようなフレーバーであっても、最初の手段であってはなりません。

于 2012-09-07T17:31:45.853 に答える
0

正規表現を使用してもよろしいですか?文字列が比較的小さい場合や実行時間が大きな問題ではない場合は、文字列ビルダーとループを使用して「?」の数を数えることができます。例えば

    //Your String
    String x = "Hello??'World'Hello?'World";
    StringBuilder sb = new StringBuilder();
    //Holds your splits
    ArrayList<String> parts = new ArrayList<String>();

    int questionmarkcount = 0;
    int _isEven;

    for (char c : x.toCharArray()) {
        if (c == '?') {
            questionmarkcount++;
            sb.append(c);
        } else if (c == '\'') {
            _isEven = questionmarkcount % 2;
            //if there are an even number of '? or none
            if (_isEven == 0 || questionmarkcount == 0) {
                //add the current split, reset the ? count and clear the String builder
                parts.add(sb.toString());
                sb.delete(0, sb.length());
                questionmarkcount = 0;
            } else {
                //append the question mark, no split is needed
                sb.append(c);
                //start counting from the beginning
                questionmarkcount = 0;
            }
        } else {
            sb.append(c);
        }
    }
    parts.add(sb.toString());

ループの終わりまでに、パーツArrayListはすべての分割を保持します。'の前に疑問符が偶数個ある場合、現在のコードは分割されます。

于 2012-09-07T12:34:19.633 に答える