当前位置:  开发笔记 > 编程语言 > 正文

Java相当于PHP的preg_replace_callback

如何解决《Java相当于PHP的preg_replace_callback》经验,为你挑选了2个好方法。

我正在将应用程序从PHP迁移到Java,并且在代码中大量使用正则表达式.我在PHP中遇到过似乎没有java等价物的东西:

preg_replace_callback()

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

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

在Java中这样做的理想方法是什么?



1> Jan Goyvaert..:

当你可以在循环中使用appendReplacement()和appendTail()时,尝试模拟PHP的回调功能似乎是一项非常多的工作:

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


这是正确的答案.接受的答案将因某些输入而失败,因为它调用`.reset()`
我认为一些JDK类确实具有强大的功能,但这些功能有时隐藏在奇怪的类名或奇怪的方法名后面......虽然这里使用的`appendReplacement/appendTail`策略需要更少的代码,`回调`策略( OP的选择答案)更清晰,更明显!

2> jdmichal..:

重要提示:正如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 "";
    }
};

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

对于这个特定的用例,最好简单地对回调中的每个匹配进行排队,然后再向后运行它们.这将防止在修改字符串时重新映射索引.


这有一个错误,你在每次循环迭代结束时调用matcher.reset().如果替换字符串与模式匹配,您将进入无限循环.使用appendReplacment()和appendTail()与StringBuffer会更安全.
推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有