2017-09-03 13 views
1

私は、次のサイクルがありますパターンマッチが無限ループにサイクルを置き換える

public class Main { 

    public static void main (String[] args){ 
     String test = "#{value} lorem ipsum #{value} lorem ipsum"; 
     String regex = "(#\\{)([^}]*)(})"; 

     Pattern callPattern = Pattern.compile(regex); 
     Matcher callMatcher = callPattern.matcher(test); 

     while (callMatcher.find()) { 
      test = callMatcher.replaceFirst(generate()); 
     } 

     System.out.println(test); 
    } 

    private static String generate(){ 
     Random random = new Random(); 
     return String.valueOf(random.nextInt(100)); 
    } 

} 

と実行が私のwhileループで立ち往生し。私は過去に似たようなアルゴリズムを使用しています。それは、最初のオカレンスを置き換えることができるように見えるが、2番目のオカレンスを見つけるが、決してそれを置き換えることはない。その理由は、あなたのケースでのMatcherあることがwhileループ内では同じまま

答えて

2

Matcher callMatcher = callPattern.matcher(test); 

while (callMatcher.find()) { // same value for matcher 
    test = callMatcher.replaceFirst(generate()); // you just keep updating the same #{value} everytime 
} 

変更し、これに:

Matcher callMatcher = callPattern.matcher(test); 

while (callMatcher.find()) { 
    test = callMatcher.replaceFirst(generate()); 
    callMatcher = callPattern.matcher(test); // updates the matcher with replaced text 
} 
+1

ありがとうございます。できます。今私が以前に働いた他の同様のサイクルがどうだったのだろうか。私は同じプロジェクトに少なくとももう1つは持っています。 – EBM

2

あなたはまた、完全にマッチャを避け、代わりにだけに頼ることができます基本文字列関数String#matchesおよびString#replaceFirst

String test = "#{value} lorem ipsum #{value} lorem ipsum"; 
while (test.matches(".*#\\{[^}]*\\}.*")) { 
    test = test.replaceFirst("#\\{[^}]*\\}", generate()); 
} 
System.out.println(test); 

出力:ここ

87 lorem ipsum 57 lorem ipsum 

デモ:

Rextester

0

質問はすべてが簡単ではありません。 testに割り当てる

Matcher callMatcher = callPattern.matcher(test); 

    while (callMatcher.find()) { 
     test = callMatcher.replaceFirst(generate()); 

マッチャー内の文字列を置き換えるものではありません:それは、このコードでは事実です。

しかし、callMatcher.find()は通常の次にの一致が見つかるため、状況を完全には説明できません。 whileループの本体に応じて、whileループが2回だけ実行されることを意味します。では、なぜこの場合無限ループするのですか?

マッチャーがリセットされていることと関係があります。 find()ためjavadocは言う:

方法の 以前の呼び出しが成功したとマッチャが は以来ではない最初の文字で、リセットされていない場合、このメソッドは、この正規表現エンジンの地域の初めに開始し、または前回の試合で と一致しました。

文の最後の半分はマッチャがリセットされない場合、その後、find()find()は二回しか成功することを意味し、パターンの発生を見つけるでしょう、そしてwhileループがあることを意味します出口。しかしjavadocMatcherでこのことについてreplaceFirst()を言う:

このメソッドは、最初にこの正規表現エンジンをリセットします。

したがって、マッチャーがリセットされてから、find()は最後の一致が途絶えた場所ではなく、先頭からそれぞれ検索します。これはあなたのコメントの質問、他の場所でコードがなぜ機能するのかを説明するかもしれません。マッチャーをリセットするものを呼び出していない可能性があります。

おそらく、パターンの各オカレンスを置き換える場合のこのような状況を処理する最も良い方法は、appendReplacementappendTailを使用することです。 appendReplacementjavadocには、その使用方法を示す良い例があります。

関連する問題