Reputation: 225281
How can I keep track of the current match’s offset from the start of the string in the callback of preg_replace_callback
?
For example, in this code, I’d like to point to the location of the match that throws the exception:
$substituted = preg_replace_callback('/{([a-z]+)}/', function ($match) use ($vars) {
$name = $match[1];
if (isset($vars[$name])) {
return $vars[$name];
}
$offset = /* ? */;
throw new Exception("undefined variable $name at byte $offset of template");
}, $template);
Upvotes: 5
Views: 2248
Reputation: 225281
As of PHP 7.4.0, preg_replace_callback
also accepts the PREG_OFFSET_CAPTURE
flag, turning every match group into a [text, offset]
pair:
$substituted = preg_replace_callback('/{([a-z]+)}/', function ($match) use ($vars) {
$name = $match[1][0];
if (isset($vars[$name])) {
return $vars[$name];
}
$offset = $match[0][1];
throw new Exception("undefined variable $name at byte $offset of template");
}, $template, flags: PREG_OFFSET_CAPTURE);
Upvotes: 1
Reputation: 12562
You can match first with preg_match_all
& PREG_OFFSET_CAPTURE
option and rebuild your string, instead of using the default preg_replace
method.
Upvotes: 2
Reputation: 4359
As the marked answer is no longer available, here's what worked for me to get current index of replacement:
$index = 0;
preg_replace_callback($pattern, function($matches) use (&$index){
$index++;
}, $content);
As you can see we have to maintain the index ourselves with the use of out-of-scope variable.
Upvotes: 7