Reputation: 5183
$s='123///456***789';
now I try to replace repeating ///
and ***
$s=preg_replace('!\/+!',"/",$s);
$s=preg_replace('!\*+!',"*",$s);
The result is 123/456*789
Ok
I'm trying to remove repeatings with the one pattern but I can't get how to set corresponding character for each repeating character
$s=preg_replace('![\/\*]+!',"/",$s);
The result is 123/456/789
but I need it to be like the above result - 123/456*789
Upvotes: 1
Views: 270
Reputation: 14409
Using back references (https://www.php.net/manual/en/regexp.reference.back-references.php):
$s='123///456***789';
$s = preg_replace ('~([\/\*])\1+~', '\1', $s);
printf ("%s\n", $s);
Upvotes: 2
Reputation: 20899
You can use a preg_replace_callback
to achieve that:
$s=preg_replace_callback('!(\*+|\/+)!' ,
function($match){
//whatever we match MULTIPLE times - replace it with one time "that".
return substr($match[1],0,1); //first matchgroup
}
,$s);
Side note: The Pattern ![\/\*]+!
will also match /*/*/*
- which is not what you (maybe) want to achieve. You should use (\*+|\/+)
instead.
Side note 2: Inside MatchGroups you do not need to escape. [/*]+
would be equal to the regex you provided.
If you design the pattern a little more tricky, you can ommit the callback, and work with a backreference:
$s=preg_replace('!(?:(\*)\*+|(\/)\/+)!' , "$1$2", $s);
Explanation:
this matches one time either *
or /
, followed by 1 or more of them. Your first matchgroup (respectively second) will now contain only ONE of the sign in question. Therefore, the whole match of ***
will be replaced with your first (respectively second) match group - which is a single *
(respectively /
) now.
using $1$2
as replacement is safe, because due to the OR (|
) One of those matchgroups is ALWAYS empty.
But i'd prefer solution one, as it is way clearer.
Upvotes: 1