2010-10-15 1 views
23

Я использую while(matcher.find()) для прокрутки всех совпадений шаблона. Для каждого экземпляра или соответствия этого шаблона он находит, я хочу заменить matcher.group(3) на новый текст. Этот текст будет отличаться для каждого из них, поэтому я использую matcher.appendReplacement(), чтобы перестроить исходную строку с новыми изменениями по мере ее прохождения. Однако appendReplacement() заменяет весь шаблон вместо группы.Как appendReplacement в группе Matcher вместо всего шаблона?

Как это сделать, но только изменить третью группу матча, а не весь шаблон?

Вот несколько примеров кода:

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

, но я хотел бы сделать что-то вроде этого (очевидно, что это не работает).

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

Нечто подобное, где оно заменяет определенную группу, а не весь шаблон.

EDIT: изменил пример регулярного выражения, чтобы показать, что не весь шаблон сгруппирован.

ответ

16

Скажем, весь ваш шаблон соответствует "(prefix)(infix)(suffix)", захватывая 3 части на группы 1, 2 и 3 соответственно. Предположим, вы хотите заменить только группу 2 (инфикс), оставив префикс и суффикс неповрежденными так, как они были.

Тогда что вы делаете, вы добавляете, что group(1) соответствует (без изменения), новая замену group(2), и то, что group(3) согласованной (без изменения), так что-то вроде этого:

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

Это будет по-прежнему соответствовать и заменить весь шаблон, но поскольку группы 1 и 3 остаются нетронутыми, фактически заменяется только инфикс.

Вы должны иметь возможность адаптировать один и тот же базовый метод для вашего конкретного сценария.

+0

Это большое спасибо. Есть ли способ сделать это, если есть некоторые аспекты шаблона, которые не входят в группы? (Я отредактировал пример моего оригинального сообщения) – cottonBallPaws

+1

Если вы должны включить эти части в соответствие (т. Е. Вы не можете оставить их вне шаблона), то вы захотите их захватить в группу, чтобы вы могли помнить, что они соответствовали и вернуть их в неизмененную часть вашей замены. – polygenelubricants

+0

Обратите внимание, что это не сработает, если одна из согласованных строк содержит '$'. См. Ответ Уоррена ниже. – Mene

27

Я вижу, что у этого уже есть принятый ответ, но он не совсем корректен. Правильный ответ, кажется, что-то вроде этого:

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

Это также показывает, что «$» это специальный символ в .appendReplacement. Поэтому вы должны позаботиться о своей функции «process()», чтобы заменить все «$» на «\ $». Matcher.quoteReplacement (replacementString) сделает это за вас (спасибо @Med)

Предыдущий принятый ответ не удастся, если в группах 1 или 3 содержится «$». Вы получите «java.lang.IllegalArgumentException: ссылка на нелегальную группу»

+10

Чтобы решить эту проблему '' '', Matcher.quoteReplacement (replacementString) 'делает трюк красиво. – Med