2010-10-15 11 views
23

Używam while(matcher.find()) do zapętlenia wszystkich dopasowań wzorca. Dla każdej instancji lub dopasowania tego wzorca znajduje on, chcę zastąpić matcher.group(3) z nowym tekstem. Ten tekst będzie inny dla każdego, więc używam matcher.appendReplacement(), aby odbudować oryginalny ciąg z nowymi zmianami podczas jego przechodzenia. Jednak appendReplacement() zastępuje cały wzór zamiast tylko grupy.Jak dodaćReplacement w grupie Matchera zamiast całego wzorca?

Jak mogę to zrobić, ale modyfikować tylko trzecią grupę dopasowania, a nie cały wzór?

Oto przykładowy kod:

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)); 
} 

ale chciałbym zrobić coś takiego (oczywiście to nie działa).

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

Coś w tym stylu, w którym zastępuje tylko określoną grupę, a nie cały Wzór.

EDYCJA: zmieniono przykład regex, aby pokazać, że nie wszystkie wzory są pogrupowane.

Odpowiedz

16

Załóżmy, że Twój cały wzór pasuje do "(prefix)(infix)(suffix)", przechwytując 3 części na grupy odpowiednio 1, 2 i 3. Teraz załóżmy, że chcesz zastąpić tylko grupę 2 (infiks), pozostawiając przedrostek i sufiks w stanie nienaruszonym tak, jak były.

To co robisz jest dołączeniu co group(1) dopasowane (niezmieniony), nowy zamiennik group(2) i co group(3) dopasowany (niezmieniony), więc coś takiego:

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

ten będzie nadal dopasować i zastąpić cały wzór, ale ponieważ grupy 1 i 3 pozostają nietknięte, tylko zamiennik zostaje zastąpiony.

Powinieneś być w stanie dostosować tę samą podstawową technikę do konkretnego scenariusza.

+0

To wielkie dzięki. Czy istnieje również sposób, aby to zrobić, jeśli istnieją pewne aspekty Wzorca, które nie występują w grupach? (Edytowałem przykład mojego oryginalnego wpisu) – cottonBallPaws

+1

Jeśli musisz uwzględnić te części w meczu (tj. Nie możesz ich pominąć), wtedy chcesz je przechwycić w grupie, abyś mógł zapamiętać, co im pasowało i umieścić je z powrotem w niezmienionej formie jako część zamiennika. – polygenelubricants

+0

Należy zauważyć, że to się nie powiedzie, jeśli jeden z dopasowanych łańcuchów zawiera '$'. Zobacz odpowiedź Warrensa poniżej. – Mene

27

Widzę, że ma już zaakceptowaną odpowiedź, ale nie jest ona w pełni poprawna. Prawidłowa odpowiedź wydaje się być coś takiego:

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

ilustruje to również, że „$” jest szczególną postacią .appendReplacement. Dlatego musisz zająć się funkcją "process()", aby zastąpić wszystkie "$" przez "\ $". Matcher.quoteReplacement (replacementString) zrobi to za ciebie (dzięki @Med)

Poprzednia zaakceptowana odpowiedź nie powiedzie się, jeśli w obu grupach 1 lub 3 zdarzy się "$". Kończy się to "java.lang.IllegalArgumentException: Nielegalne odniesienie do grupy"

+10

Aby rozwiązać ten problem '$', 'Matcher.quoteReplacement (replacementString)' ładnie działa. – Med

Powiązane problemy