2011-12-22 19 views
38

bất cứ ai có thể cho tôi tại saoString.replaceAll (regex) làm cho việc thay thế cùng một hai lần

System.out.println("test".replaceAll(".*", "a")); 

Kết quả trong

aa 

Lưu ý rằng sau đây có kết quả tương tự:

System.out.println("test".replaceAll(".*$", "a")); 

Tôi đã thử nghiệm điều này trên java 6 & 7 và cả hai dường như hành xử theo cùng một cách. Tôi có thiếu thứ gì đó hoặc đây có phải là lỗi trong công cụ regex java không?

Trả lời

57

Đây không phải là bất thường: .* có thể khớp với bất kỳ thứ gì.

Bạn hỏi thay thế tất cả lần xuất hiện:

  • sự xuất hiện đầu tiên thực hiện phù hợp với toàn bộ dây, động cơ regex do đó bắt đầu từ ngày kết thúc đầu vào cho trận đấu tới;
  • nhưng .* cũng khớp với một chuỗi rỗng! Do đó, nó khớp với một chuỗi rỗng ở cuối đầu vào và thay thế bằng a.

Thay vào đó, sử dụng .+ sẽ không hiển thị vấn đề này vì regex này không thể khớp với chuỗi trống (yêu cầu ít nhất một ký tự để khớp).

Hoặc, sử dụng .replaceFirst() chỉ thay thế sự xuất hiện đầu tiên:

"test".replaceFirst(".*", "a") 
     ^^^^^^^^^^^^ 

Bây giờ, tại sao .* cư xử như nó làm và không phù hợp hơn hai lần (nó có thể về mặt lý thuyết) là một điều thú vị để xem xét . Xem bên dưới:

# Before first run 
regex: |.* 
input: |whatever 
# After first run 
regex: .*| 
input: whatever| 
#before second run 
regex: |.* 
input: whatever| 
#after second run: since .* can match an empty string, it it satisfied... 
regex: .*| 
input: whatever| 
# However, this means the regex engine matched an empty input. 
# All regex engines, in this situation, will shift 
# one character further in the input. 
# So, before third run, the situation is: 
regex: |.* 
input: whatever<|ExhaustionOfInput> 
# Nothing can ever match here: out 

Lưu ý rằng, như @ A.H. ghi chú trong các chú thích, không phải tất cả các công cụ regex đều hoạt động theo cách này. Ví dụ, GNU sed sẽ xem xét rằng nó đã cạn kiệt đầu vào sau trận đấu đầu tiên.

+0

Đồng ý. Điều này cũng đúng với Perl. 'perl -le '$ x =" test "; $ x = ~ s /.*/ a/g; in $ x'' sản lượng "aa". –

+7

@ChrisDolan: 'sed' chỉ tạo ra' a', nhưng tôi nghi ngờ một lỗi của nó. :-) –

+0

@ A.H. có thực sự ... Tôi cần phải đọc "Mastering Regular Expressions" một lần nữa – fge

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