Java 相当于 PHP 的preg_replace_callback

2022-08-30 12:38:05

我正在将应用程序从PHP移动到Java,并且在代码中大量使用正则表达式。我在PHP中遇到了一些似乎没有Java等效物的东西:

preg_replace_callback()

对于正则表达式中的每个匹配项,它调用一个函数,该函数将匹配文本作为参数传递。作为示例用法:

$articleText = preg_replace_callback("/\[thumb(\d+)\]/",'thumbReplace', $articleText);
# ...
function thumbReplace($matches) {
   global $photos;
   return "<img src=\"thumbs/" . $photos[$matches[1]] . "\">";
}

在Java中做到这一点的理想方法是什么?


答案 1

尝试模拟PHP的回调功能似乎需要做很多工作,而你可以在循环中使用 appendReplacement() 和 appendTail():

StringBuffer resultString = new StringBuffer();
Pattern regex = Pattern.compile("regex");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
  // You can vary the replacement text for each match on-the-fly
  regexMatcher.appendReplacement(resultString, "replacement");
}
regexMatcher.appendTail(resultString);

答案 2

重要说明:正如 Kip 在注释中指出的那样,如果匹配的正则表达式与替换字符串匹配,则此类存在无限循环错误。如有必要,我将把它作为一个练习留给读者来修复它。


我不知道Java中内置了类似的东西。你可以毫不费力地使用 Matcher 类来滚动自己:

import java.util.regex.*;

public class CallbackMatcher
{
    public static interface Callback
    {
        public String foundMatch(MatchResult matchResult);
    }

    private final Pattern pattern;

    public CallbackMatcher(String regex)
    {
        this.pattern = Pattern.compile(regex);
    }

    public String replaceMatches(String string, Callback callback)
    {
        final Matcher matcher = this.pattern.matcher(string);
        while(matcher.find())
        {
            final MatchResult matchResult = matcher.toMatchResult();
            final String replacement = callback.foundMatch(matchResult);
            string = string.substring(0, matchResult.start()) +
                     replacement + string.substring(matchResult.end());
            matcher.reset(string);
        }
    }
}

然后致电:

final CallbackMatcher.Callback callback = new CallbackMatcher.Callback() {
    public String foundMatch(MatchResult matchResult)
    {
        return "<img src=\"thumbs/" + matchResults.group(1) + "\"/>";
    }
};

final CallbackMatcher callbackMatcher = new CallbackMatcher("/\[thumb(\d+)\]/");
callbackMatcher.replaceMatches(articleText, callback);

请注意,可以通过调用 或 来获取整个匹配的字符串,因此不必将回调传递当前字符串状态。matchResults.group()matchResults.group(0)

编辑:使它看起来更像是PHP函数的确切功能。

这是原文,因为提问者喜欢它:

public class CallbackMatcher
{
    public static interface Callback
    {
        public void foundMatch(MatchResult matchResult);
    }

    private final Pattern pattern;

    public CallbackMatcher(String regex)
    {
        this.pattern = Pattern.compile(regex);
    }

    public String findMatches(String string, Callback callback)
    {
        final Matcher matcher = this.pattern.matcher(string);
        while(matcher.find())
        {
            callback.foundMatch(matcher.toMatchResult());
        }
    }
}

对于此特定用例,最好只是在回调中对每个匹配项进行排队,然后向后运行它们。这样可以避免在修改字符串时必须重新映射索引。


推荐