Что эквивалентно Regex-replace-with-function-оценке в Java 7?
Я ищу очень простой способ получить эквивалент чего-то вроде следующего кода JavaScript. То есть для каждого совпадения я хотел бы вызвать определенную функцию преобразования и использовать результат в качестве значения замены.
var res = "Hello World!".replace(/\S+/, function (word) {
// Since this function represents a transformation,
// replacing literal strings (as with replaceAll) are not a viable solution.
return "" + word.length;
})
// res => "5 6"
Только.. в Java. И, предпочтительно, как "единственный метод" или "шаблон", который можно использовать повторно.
Ответы
Ответ 1
Ваш ответ находится в документации Matcher # appendReplacement. Просто поместите вызов своей функции в цикл while.
[Метод appendReplacement] предназначен для использования в цикле вместе с методами appendTail и find. Следующий код, например, записывает одну собаку двух собак во дворе в поток стандартного вывода:
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());
Ответ 2
При разрешении Java 8 вы можете использовать лямбда-выражения, чтобы JavaScript заменял:
String result = StringReplacer.replace("Hello World!", Pattern.compile("\\S+"), m -> ("" + m.group().length()));
StringReplacer.java:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringReplacer {
public static String replace(String input, Pattern regex, StringReplacerCallback callback) {
StringBuffer resultString = new StringBuffer();
Matcher regexMatcher = regex.matcher(input);
while (regexMatcher.find()) {
regexMatcher.appendReplacement(resultString, callback.replace(regexMatcher));
}
regexMatcher.appendTail(resultString);
return resultString.toString();
}
}
StringReplacerCallback.java:
import java.util.regex.Matcher;
public interface StringReplacerCallback {
public String replace(Matcher match);
}
Источник: http://www.whitebyte.info/programming/string-replace-with-callback-in-java-like-in-javascript
Ответ 3
Начиная с Java 9 Matcher.replaceAll
:
Pattern.compile("\\S+").matcher("Hello World!")
.replaceAll(mr -> "" + mr.group().length());
Параметр со свободным названием mr
- это MatchResult
с такими методами доступа, как mr.group(1)
или mr.end() - mr.start()
.
Ответ 4
Не знаю, каковы ваши точные требования, но что-то вроде этого может работать:
String res = "";
for (String piece : "hello world".split(" "))
res += Integer.toString(piece.length()) + " ";
Конечно, есть и другие способы написать это и твики, которые могут быть сделаны в зависимости от требований (например, используйте более точный разделитель, чем пробел).
Для точной реализации вашего фрагмента можно использовать, например, StreamTokenizer
с помощью StringReader
и некоторых оберток для разбора разделителей и вставки их между подсчетами.