Regex version of strtr (simultaneous replacements)

Any questions involving matching text strings to patterns - the pattern is called a "regular expression."

Moderator: General Moderators

Post Reply
lwc
Forum Commoner
Posts: 35
Joined: Thu Jan 11, 2007 11:04 am

Regex version of strtr (simultaneous replacements)

Post 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!
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: Regex version of strtr (simultaneous replacements)

Post 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.
lwc
Forum Commoner
Posts: 35
Joined: Thu Jan 11, 2007 11:04 am

Re: Regex version of strtr (simultaneous replacements)

Post 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,
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: Regex version of strtr (simultaneous replacements)

Post 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.
lwc
Forum Commoner
Posts: 35
Joined: Thu Jan 11, 2007 11:04 am

Re: Regex version of strtr (simultaneous replacements)

Post by lwc »

Adding this inside the loop:

Code: Select all

print_r($value);print_r($offset);
Displays:
Array
(
[0] => other
[1] => 2
)
Array
(
[0] => other
[1] => 8
)
So I'm not sure what do do with it.
User avatar
ridgerunner
Forum Contributor
Posts: 214
Joined: Sun Jul 05, 2009 10:39 pm
Location: SLC, UT

Re: Regex version of strtr (simultaneous replacements)

Post 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;
?>
:)
lwc
Forum Commoner
Posts: 35
Joined: Thu Jan 11, 2007 11:04 am

Re: Regex version of strtr (simultaneous replacements)

Post 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...
Post Reply