27

Java の正規表現の実装で予期しない動作を確認しました。と を使用する場合、Matcher のメソッドを使用するjava.util.regex.Patternjava.util.regex.Matcher、次の正規表現は入力で正しく一致しません。"Merlot"find()

((?:White )?Zinfandel|Merlot)

最も外側の一致するグループ内の式の順序を変更すると、Matcher のfind()メソッド一致します。

(Merlot|(?:White )?Zinfandel)

問題を説明するテスト コードを次に示します。

RegexTest.java

import java.util.regex.*;

public class RegexTest {
    public static void main(String[] args) {
        Pattern pattern1 = Pattern.compile("((?:White )?Zinfandel|Merlot)");
        Matcher matcher1 = pattern1.matcher("Merlot");
        // prints "No Match :("
        if (matcher1.find()) {
            System.out.println(matcher1.group(0));
        } else {
            System.out.println("No match :(");
        }

        Pattern pattern2 = Pattern.compile("(Merlot|(?:White )?Zinfandel)");
        Matcher matcher2 = pattern2.matcher("Merlot");
        // prints "Merlot"
        if (matcher2.find()) {
            System.out.println(matcher2.group(0));
        } else {
            System.out.println("No match :(");
        }
    }
}

予想される出力は次のとおりです。

Merlot
Merlot

しかし、実際の出力は次のとおりです。

No Match :(
Merlot

この予期しない動作が、Ubuntu Linux の Java バージョン 1.7.0_11 と、OSX 10.8.2 の Java バージョン 1.6.0_37 に存在することを確認しました。昨日、この動作をバグとしてOracleに報告したところ、バグ レポートが受信され、内部レビュー ID が 2441589 であることを知らせる自動電子メールが返されました。バグでその ID を検索しても、バグ レポートが見つかりません。データベース。(コオロギの鳴き声が聞こえますか?)

おそらく完全にテストされ、使用されている Java の正規表現実装 (2013 年には信じがたいこと) のバグを発見したのでしょうか、それとも何か間違ったことをしているでしょうか?

4

4 に答える 4

8

以下:

import java.util.regex.*;

public class T {
  public static void main( String args[] ) {
    System.out.println( Pattern.compile("(a)?bb|c").matcher("c").find() );
    System.out.println( Pattern.compile("(a)?b|c").matcher("c").find() );
  }
}

版画

false
true

の上:

  • JDK1.7.0_13
  • JDK1.6.0_24

以下:

import java.util.regex.*;

public class T {
  public static void main( String args[] ) {
    System.out.println( Pattern.compile("((a)?bb)|c").matcher("c").find() );
    System.out.println( Pattern.compile("((a)?b)|c").matcher("c").find() );
  }
}

プリント:

true
true
于 2013-02-05T17:51:08.817 に答える
2

何が起こっているのか理解できませんが、バグレポートに追加できる可能性のある診断情報を抽出するために、あなたの例を試してみました.

まず、所有量指定子を使用すると機能しますが、その理由はわかりません。

Pattern pattern1 = Pattern.compile("((?:White )?+Zinfandel|Merlot)");

また、選択した最初のグループが 2 番目のグループよりも短い場合は、どちらの方法でも機能します。

Pattern pattern1 = Pattern.compile("((?:White )?Zinf|Merlot)");

私が言ったように、私はこれがどのようになるのか本当に理解していません。これらの 2 つの調査結果はどれも私には意味がありませんが、共有したいと思いました...

于 2013-02-05T18:51:32.737 に答える
2

このバグはJava 8 で明らかに修正され、Java 7 へのバックポートとして「修正されません」で解決されました。ただし、回避策として、「ホワイト」の独立した (アトミック) グループを使用するか、テストを分離することができます。別の交互試験グループにラップすることにより、「ホワイトジンファンデル」のケース。

あなたの例では、次の最初のキャプチャグループ内に非キャプチャ グループがあります。

非捕捉グループ修飾子(?:White)

((?:White )?Zinfandel|Merlot)

回避策として、独立したキャプチャ グループを使用すると成功します。

独立した非捕捉グループ修飾子(?>White)

((?>White )?Zinfandel|Merlot)

Java 1.7.0_71 で、独立した非キャプチャー グループまたはグループ交替のいずれかのテスト ケースを再作成すると機能します。

java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)

独立した非キャプチャ グループまたはグループ交替

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest {

    public static void main( String[] args ) {

        Pattern independentNCG = Pattern.compile( "((?>White )?Zinfandel|Merlot)" );
        Matcher independentNCGMatcher = independentNCG.matcher( "Merlot" );

        Pattern alternateGroupPattern = Pattern.compile( "(((?:White )?Zinfandel)|Merlot)" );
        Matcher alternateGroupMatcher = alternateGroupPattern.matcher( "Merlot" );

        System.out.println( independentNCGMatcher.find() ? independentNCGMatcher.group( 0 ) : "No match found for Merlot" );
        System.out.println( alternateGroupMatcher.find() ? alternateGroupMatcher.group( 0 ) : "No match found for Merlot" );

    }
}

戻り値

Merlot
Merlot
于 2014-12-19T22:19:33.510 に答える