Page 1 of 1
Regex version of strtr (simultaneous replacements)
Posted: Sat Mar 06, 2010 3:02 pm
by lwc
preg_replace can't do simultaneous replacements.
strtr can't use regex. How can one get simultaneous replacement with regex (e.g. case insensitive)?
Code: Select all
$switch_str = array(
"other" => "thing",
"thing" => "other"
);
$switch_preg = array(
"/\bother\b/i" => "thing",
"/\bthing\b/i" => "other"
);
$input = "Another other thing"; // the needed output is "Another thing other"
echo preg_replace(array_keys($switch_preg), array_values($switch_preg), $input); // Another other other (due to a re-switch)
echo "<br>";
echo strtr($input, $switch_str); // Anthing thing other ("anthing" is the result of using no regex)
Thanks!
Re: Regex version of strtr (simultaneous replacements)
Posted: Sat Mar 06, 2010 5:37 pm
by John Cartwright
lwc wrote:preg_replace can't do simultaneous replacements.
Not sure what you mean by this, preg_replace() can accept an array of patterns and replacements.
Re: Regex version of strtr (simultaneous replacements)
Posted: Sat Mar 06, 2010 6:18 pm
by lwc
Simultaneous means replacing more than one thing at the same time. You can call it parallel replacing too. Some quotes that may help:
if you are using the preg_replace with arrays, the replacements will apply as subject for the patterns later in the array. This means replaced values can be replaced again.
if you go straight and substitute all 'A's wit 'T's you can't tell for sure which 'T's to substitute with 'A's afterwards.
In other words, the array is just a shortcut to run multiple preg_replace. It doesn't act like strtr, which doesn't re-replace what was already replaced:
strtr() will always look for the longest possible match first and will *NOT* try to replace stuff that it has already worked on,
Re: Regex version of strtr (simultaneous replacements)
Posted: Sat Mar 06, 2010 7:35 pm
by John Cartwright
In that case you will probably need to tokenize your replacements, and perform the replacement as an additonal step.
Code: Select all
$switch_preg = array(
"other" => "thing",
"thing" => "other"
);
$pattern = '~'. implode('|', array_map('preg_quote', array_keys($switch_preg))) .'~i';
if (preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE )) {
foreach ($matches as $tokens) {
list($value, $offset) = $tokens;
//$subject = substr_replace( ... );
}
}
Haven't really thought this through, but I have to run and will leave you to test and implement. Good luck.
Re: Regex version of strtr (simultaneous replacements)
Posted: Sat Mar 06, 2010 7:49 pm
by lwc
Adding this inside the loop:
Displays:
Array
(
[0] => other
[1] => 2
)
Array
(
[0] => other
[1] => 8
)
So I'm not sure what do do with it.
Re: Regex version of strtr (simultaneous replacements)
Posted: Sun Mar 07, 2010 11:10 am
by ridgerunner
This is a classic case with a simple solution - you must add another intermediate replacement step. Something like this:
Code: Select all
<?php
$input = "Another other thing"; // the needed output is "Another thing other"
$patterns = array(
'/\bother\b/i', // "other" => "x_temp_x"
'/\bthing\b/i', // "thing" => "other"
'/\bx_temp_x\b/'); // "x_temp_x" => "thing"
$replaces = array(
'x_temp_x',
'other',
'thing');
$output = preg_replace($patterns, $replaces, $input);
echo $output;
?>

Re: Regex version of strtr (simultaneous replacements)
Posted: Sun Mar 07, 2010 1:18 pm
by lwc
I was about to post this:
Code: Select all
<?php
$input = "Another other thing"; // the needed output is "Another thing other"
$pattern = array(
"/\bOther\b/" => "_strtrdummy_Thing",
"/\other\b/" => "_strtrdummy_thing",
"/\bThing\b/" => "_strtrdummy_Other",
"/\bthing\b/" => "_strtrdummy_other",
"/_strtrdummy_/" => "",
);
$output = preg_replace(array_keys($pattern), array_values($pattern), $input);
echo $output;
?>
But I wish there was a direct solution, just like strtr...