I'm in the process of moving an application from PHP to Java and there is heavy use of regular expressions in the code. I've run across something in PHP that doesn't seem to have a java equivalent:
preg_replace_callback()
For every match in the regex, it calls a function that is passed the match text as a parameter. As an example usage:
$articleText = preg_replace_callback("/\[thumb(\d+)\]/",'thumbReplace', $articleText);
# ...
function thumbReplace($matches) {
global $photos;
return "<img src=\"thumbs/" . $photos[$matches[1]] . "\">";
}
What would be the ideal way to do this in Java?
I wasn't quite satisfied with any of the solutions here. I wanted a stateless solution. And I didn't want to end up in an infinite loop if my replacement string happened to match the pattern. While I was at it I added support for a
limit
parameter and a returnedcount
parameter. (I used anAtomicInteger
to simulate passing an integer by reference.) I moved thecallback
parameter to the end of the parameter list, to make it easier to define an anonymous class.Here is an example of usage:
And here is my version of ReplaceCallback class:
Here is the final result of what I did with your suggestion. I thought it would be nice to have out here in case someone has the same problem. The resulting calling code looks like:
The entire class listing follows:
IMPORTANT: As pointed out by Kip in the comments, this class has an infinite loop bug if the matching regex matches on the replacement string. I'll leave it as an exercise to readers to fix it, if necessary.
I don't know of anything similar that's built into Java. You could roll your own without too much difficulty, using the Matcher class:
Then call:
Note that you can get the entire matched string by calling
matchResults.group()
ormatchResults.group(0)
, so it's not necessary to pass the callback the current string state.EDIT: Made it look more like the exact functionality of the PHP function.
Here's the original, since the asker liked it:
For this particular use case, it might be best to simply queue each match in the callback, then afterwards run through them backwards. This will prevent having to remap indexes as the string is modified.
Trying to emulate PHP's callback feature seems an awful lot of work when you could just use appendReplacement() and appendTail() in a loop:
I found that jdmichal's answer would infinite loop if your returned string could be matched again; below is a modification which prevents infinite loops from this matching.
Usage example:
will produce the return value: