1

私は主に数字を一致させようとしていますが、表現に続く単語に応じて、違いを生む必要があります。

°C や時間指定などの温度用語が後に続かないすべての数値に一致します。私の正規表現は次のようになります。

(((\d+?)(\s*)(\-)(\s*))?(\d+)(\s*))++(?!minuten|Minuten|min|Min|Stunden|stunden|std|Std|°C| °C)

例を次に示します: http://regexr.com?33jeg

この動作は私が期待したものですが、Java は次のことを行います: インデックスは、マッチ 4 に対応するグループです。

0: "4 "1: "4 "2: "0 - "3: "0"4: " "5: "-"6: " "7: "4"8: " "9: "°C"

すべての文字列を個別に照合することを知っておく必要があります。したがって、5 の一致は次のようになります。

0: "5 "1: "5 "2: "null"3: "null"4: "null"5: "null"6: "null"7: "5"8: " "9: "null"

これは、他の試合がどのようになりたいかです。この不快な動作は、「-」が一致の前の文字列のどこかにある場合にのみ発生します

私のJavaコードは次のとおりです。

public static void adaptPortionDetails(EList<Step> steps, double multiplicator){
    
    String portionMatcher = "(((\\d+?)(\\s*)(\\-)(\\s*))?(\\d+)(\\s*))++(?!°C|Grad|minuten|Minuten|min|Min|Stunden|stunden|std|Std)";
    
    for (int i = 0; i < steps.size(); i++) {
        Matcher matcher = Pattern.compile(portionMatcher).matcher(
                steps.get(i).getDescription());
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            printGroups(matcher);
            String newValue1Str;
            if (matcher.group(3) == null){
                newValue1Str = "";
                System.out.println("test");
            }else{
                double newValue1 = Integer.parseInt(matcher.group(3)) * multiplicator;
                newValue1Str = Fraction.getFraction(newValue1).toProperString();
            }
            double newValue2 = Integer.parseInt(matcher.group(7)) * multiplicator;
            String newValue2Str = Fraction.getFraction(newValue2).toProperString();
            
            
            matcher.appendReplacement(sb, newValue1Str + "$4$5$6" + newValue2Str + "$8");
        }
        matcher.appendTail(sb);
        steps.get(i).setDescription(sb.toString());
    }
}

私が欠けているものを教えていただければ幸いです。

4

1 に答える 1

0

これは、Java の実装におけるバグ (または機能?) のようです。次のインデックスから照合をやり直す必要がある場合、キャプチャ グループのキャプチャされたテキストがリセットされないようです。

このテストは、Java 正規表現エンジンと PHP の PCRE の間の動作の不一致を明らかにします。

  • 正規表現:(\d+(-\d+)?){1}+(?!x)
  • 入力:34 34-43x 78 90
  • Java の結果: 3 つの一致 ( 347890)。第2試合の2回目の捕獲組は-43. 2 番目のキャプチャ グループは、1 番目と 3 番目の一致で何もキャプチャしません。
  • PHP 結果: 同じ 3 つの一致がありますが、2 番目のキャプチャ グループはすべての一致に対して何もキャプチャしません。PHP の PCRE 実装では、一致をやり直す必要がある場合、キャプチャ グループのキャプチャされたテキストがリセットされます。

これは、JRE 6 Update 37 および JRE 7 Update 11 でテストされています。

これについても同じ結果ですが、一致をやり直す必要がある場合にキャプチャされたテキストがリセットされないことを証明するためだけに:

  • 正規表現:a(\d+(-\d+)?){1}+(?!x)
  • 入力:a34 a34-43x a78 a90
  • PHPの結果

あなたの正規表現についてのコメント

不要な数値を破棄するために一致を所有的にしながら、一度に 1 つの数値または数値の範囲を変更したいように思われるため、は である++必要があると思います。{1}+

回避策

すべて (1 つの数値または数値の範囲) をキャプチャする最初のグループ (最も外側のキャプチャ グループ) は、一致が見つかると常に上書きされます。したがって、あなたはそれに頼ることができます。-グループ 1 にa が存在するかどうかを確認できます(containsメソッドを使用)。存在する場合は、キャプチャ グループ 2 に現在の一致からキャプチャされたテキストが含まれていることがわかり、キャプチャされたテキストを使用できます。存在しない場合は、キャプチャ グループ 2 とそのネストされたキャプチャ グループのすべてのキャプチャ テキストを無視できます。

于 2013-01-30T14:25:41.343 に答える