2010-10-15 30 views
23

Tôi đang sử dụng while(matcher.find()) để lặp qua tất cả các kết quả khớp của Mẫu. Đối với mỗi trường hợp hoặc kết hợp của mẫu mà nó tìm thấy, tôi muốn thay thế matcher.group(3) bằng một số văn bản mới. Văn bản này sẽ khác nhau cho mỗi một vì vậy tôi đang sử dụng matcher.appendReplacement() để xây dựng lại chuỗi gốc với những thay đổi mới khi nó trải qua. Tuy nhiên, appendReplacement() thay thế toàn bộ Mẫu thay vì chỉ nhóm.Làm thế nào để appendReplacement trên một nhóm Matcher thay vì toàn bộ mô hình?

Làm cách nào tôi có thể thực hiện việc này nhưng chỉ sửa đổi nhóm thứ ba của trận đấu thay vì toàn bộ Mẫu?

Dưới đây là một số mã ví dụ:

Pattern pattern = Pattern.compile("THE (REGEX) (EXPRESSION) (WITH MULTIPLE) GROUPS"); 
Matcher matcher = pattern.matcher("THE TEXT TO SEARCH AND MODIFY"); 
StringBuffer buffer = new StringBuffer(); 

while(matcher.find()){ 
    matcher.appendReplacement(buffer, processTheGroup(matcher.group(3)); 
} 

nhưng tôi muốn làm một cái gì đó như thế này (rõ ràng điều này không làm việc).

... 
while(matcher.find()){ 
    matcher.group(3).appendReplacement(buffer, processTheGroup(matcher.group(3)); 
} 

Điều gì đó giống như vậy, nó chỉ thay thế một nhóm nhất định, không phải toàn bộ Mẫu.

CHỈNH SỬA: đã thay đổi ví dụ về regex để cho thấy rằng không phải tất cả mẫu đều được nhóm.

Trả lời

16

Giả sử toàn bộ mẫu của bạn khớp với "(prefix)(infix)(suffix)", chụp 3 phần thành các nhóm 1, 2 và 3 tương ứng. Bây giờ chúng ta hãy nói rằng bạn muốn thay thế chỉ nhóm 2 (infix), để lại tiền tố và hậu tố nguyên vẹn theo cách của chúng.

Sau đó, những gì bạn làm là bạn nối thêm gì group(1) phù hợp (không thay đổi gì), việc thay mới cho group(2), và những gì group(3) phù hợp (không thay đổi gì), vì vậy một cái gì đó như thế này:

matcher.appendReplacement(
    buffer, 
    matcher.group(1) + processTheGroup(matcher.group(2)) + matcher.group(3) 
); 

này vẫn sẽ phù hợp và thay thế toàn bộ mô hình, nhưng kể từ khi nhóm 1 và 3 bị bỏ hoang, chỉ có hiệu quả là infix được thay thế.

Bạn sẽ có thể điều chỉnh cùng một kỹ thuật cơ bản cho kịch bản cụ thể của mình.

+0

Đây là lời cảm ơn tuyệt vời. Có cách nào để làm điều này nếu có một số khía cạnh của Mẫu không nằm trong nhóm không? (Tôi đã chỉnh sửa ví dụ của bài đăng gốc) – cottonBallPaws

+1

Nếu bạn phải bao gồm các phần đó trong trận đấu (nghĩa là bạn không thể để chúng ra khỏi mẫu), thì bạn muốn chụp chúng trong một nhóm để bạn có thể nhớ những gì chúng khớp và đặt chúng trở lại không thay đổi gì như là một phần thay thế của bạn. – polygenelubricants

+0

Lưu ý rằng điều này sẽ thất bại nếu một trong các chuỗi phù hợp chứa '$'. Xem câu trả lời của Warrens bên dưới. – Mene

27

Tôi thấy điều này đã có câu trả lời được chấp nhận, nhưng nó không hoàn toàn chính xác. Câu trả lời đúng có vẻ giống như sau:

.appendReplacement("$1" + process(m.group(2)) + "$3"); 

Điều này cũng minh họa rằng "$" là ký tự đặc biệt trong .appendReplacement. Vì vậy, bạn phải cẩn thận trong hàm "process()" của bạn để thay thế tất cả "$" bằng "\ $". Matcher.quoteReplacement (replaceString) sẽ làm điều này cho bạn (nhờ @Med)

Câu trả lời được chấp nhận trước đó sẽ thất bại nếu một trong hai nhóm 1 hoặc 3 xảy ra chứa "$". Bạn sẽ kết thúc bằng "java.lang.IllegalArgumentException: Tham chiếu nhóm bất hợp pháp"

+10

Để giải quyết vấn đề '$' này, 'Matcher.quoteReplacement (replaceString)' thực hiện thủ thuật độc đáo. – Med

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