2011-12-29 30 views
6

thể trùng lặp:
Java regex anomaly?không thể hiểu String.replaceAll hành vi không tham lam

bất kỳ ý tưởng tại sao các thử nghiệm sau thất bại (trở về "xx" thay vì "x")

@Test 
public void testReplaceAll(){ 
    assertEquals("x", "xyz".replaceAll(".*", "x")); 
} 

Tôi không muốn làm "^.*$" .... Tôi muốn hiểu hành vi này. bất kỳ manh mối nào?

+0

"' xyz ".replaceAll (". * "," X ")' trả lại là gì? – robert

+0

@robert Nó trả về '" xx "'. –

+0

@JackEdmonds Tại sao '" xx "' chứ không phải '" xxx "'? – user219882

Trả lời

9

Có, nó chính xác giống như được mô tả trong this question!

.* đầu tiên sẽ phù hợp với toàn bộ đầu vào, nhưng sau đó cũng là một chuỗi rỗng ở phần cuối của đầu vào ...

Hãy tượng trưng cho động cơ regex với | và đầu vào với <...> trong ví dụ của bạn.

  • đầu vào: <xyz>;
  • động cơ regex, trước khi chạy lần đầu tiên: <|xyz>;
  • động cơ regex, sau lần chạy đầu tiên: <xyz|> (văn bản phù hợp: "xyz");
  • động cơ regex, sau lần chạy thứ hai: <xyz>| (văn bản phù hợp: "").

Không phải tất cả động cơ regex đều hoạt động theo cách này. Java hiện, tuy nhiên. Vì vậy, perl. Sed, như một ví dụ, sẽ định vị con trỏ của nó sau khi kết thúc đầu vào ở bước 3.

Bây giờ, bạn cũng phải hiểu một điều quan trọng: động cơ regex, khi chúng gặp phải một trận đấu không dài, luôn tiến lên một tính cách. Nếu không, hãy xem xét điều gì sẽ xảy ra nếu bạn cố gắng thay thế '^' bằng 'a': '^' khớp với một vị trí, do đó là một kết quả có độ dài bằng 0. Nếu động cơ không nâng cấp một ký tự, "x" sẽ được thay thế bằng "rìu", sẽ được thay thế bằng "aax", v.v. Vì vậy, sau trận đấu thứ hai, trống, động cơ regex của Java tiến một ký tự "... Trong đó không có bất kỳ: kết thúc xử lý.

+0

nhưng không phải là giả sử để phù hợp với tham lam? – ekeren

+0

À, nó rất tham lam, phải không? Hãy nhớ rằng '*' có nghĩa là "** ZERO ** hoặc nhiều hơn". Vì vậy, '. *' Hoàn toàn hài lòng với một chuỗi rỗng! – fge

+0

Sau khi chỉnh sửa tôi hiểu - java lặp lại trên nó phát hiện ... và khi nó đạt đến char cuối cùng nó cũng gây ra trận đấu (các trận đấu char trống ...) Cảm ơn !!! – ekeren

0
@Test 
public void testReplaceAll(){ 
    assertEquals("x", "xyz".replaceAll(".+", "x")); 
} 

lẽ sẽ làm các trick vì đó đòi hỏi một hoặc nhiều ký tự và do đó không ngăn chặn các hành vi trong đó * có thể phù hợp với zero ký tự và thay thế bằng "x".

Các vấn đề liên quan