2017-09-03 36 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

的原因是在你的情況下,匹配器仍然是while循環中相同的:

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

謝謝。有用。現在我想知道其他類似的週期是如何工作的。我在同一個項目中至少有另一個。 – EBM

2

你也可以避開匹配完整,而不是僅僅依靠鹼基字符串函數String#matchesString#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

的問題不是這麼簡單。這是真的,在此代碼:

Matcher callMatcher = callPattern.matcher(test); 

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

分配給test不替換字符串中的匹配。

但是,這並不能完全說明情況,因爲callMatcher.find()通常會發現下一個匹配的發生。取決於while循環體內的內容,這意味着while循環可能只有被執行兩次。那麼爲什麼它在這種情況下無限循環?

它與匹配器被重置有關。該javadocfind()說:

該方法始於此匹配的區域的開始,或者,如果該方法的 以前的調用是成功的,並且匹配具有 不是因爲被複位,在第一個字符不前場比賽的比賽結果爲 。

句子的後半部分意味着,如果匹配不復位,然後find()會發現下一個出現的格局,這意味着find()只成功了兩次,然後while循環會出口。但javadoc說,這大約replaceFirst()Matcher

此方法首先重置匹配器。

因此,由於匹配器被重置,所以find()將從每次開始搜索,而不是最後一次匹配的位置。這可能會解釋您評論中的問題,以及代碼爲什麼在其他地方有效。這可能是因爲你沒有調用任何重置匹配器的東西。

也許處理這種情況的最好方法就是使用appendReplacementappendTail來代替每次出現的模式。 javadocappendReplacement有一個很好的例子顯示如何使用它。