Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I replace multiple strings within a string without overlapping results?

I'm trying to create common masks from a string like so:

012abc.d+e_fg~hijk => 012{start}.d+{middle}_fg~{end}jk

replace:

$arrFromTo = array(
              'st' => '{pre}',
              'abc' => '{start}',
              'e' => '{middle}',
              'hi' => '{end}',
              'dd' => '{post}'
             );

Instead I keep overlapping replacements and get something like this instead (using a loop of str_replace's):

012{{pre}art}.d+{mi{post}le}_fg~{end}jk

Because the st is found in the already replaced {start} and dd is found in {middle}.

How would you replace the following?

$str = 'abc.d+e_fg~hijk';

echo replace_vars($str); // Desired output: 012{start}.d+{middle}_fg~{end}kJ
like image 236
Ryan Avatar asked Oct 28 '14 20:10

Ryan


People also ask

How do I replace multiple items in a string?

Replace multiple Substrings in a String using replace() It replaces all the occurrences of a sub-string to a new string by passing the old and new strings as parameters to the replace() function. Multiple calls to replace() function are required to replace multiple substrings in a string.

How do you replace multiple occurrences of a string in Java?

You can replace all occurrence of a single character, or a substring of a given String in Java using the replaceAll() method of java. lang. String class. This method also allows you to specify the target substring using the regular expression, which means you can use this to remove all white space from String.

How do you replace multiple parts of a string in Python?

01) Using replace() method Python offers replace() method to deal with replacing characters (single or multiple) in a string. The replace method returns a new object (string) replacing specified fields (characters) with new values.


2 Answers

I might misunderstand, but you don't seem to need regex for the replacing. They're simple, literal replacements.

$from = '012abc.d+e_fg~hijk';
$arrFromTo = array(
              'st' => '{pre}',
              'abc' => '{start}',
              'e' => '{middle}',
              'hi' => '{end}',
              'dd' => '{post}'
             );
$to = strtr($from, $arrFromTo); // 012{start}.d+{middle}_fg~{end}jk

strtr() is awesome. It takes a very readable input and it doesn't re-replace like your problem in the loop.

like image 77
Rudie Avatar answered Oct 31 '22 00:10

Rudie


You can use preg_replace like this:

$str = '012abc.d+e_fg~hijk';
$arrFromTo = array(
              'st' => '{pre}',
              'abc' => '{start}',
              'e' => '{middle}',
              'hi' => '{end}',
              'dd' => '{post}'
             );

$reArr=array();
foreach($arrFromTo as $k=>$v){
   $reArr['/' . $k . '(?![^{}]*})/'] = $v;
}

echo preg_replace(array_keys($reArr), array_values($reArr), $str);
//=> 012{start}.d+{middle}_fg~{end}jk

Core of this regex is this negative lookaead: (?![^{}]*})

Which avoid matching keys of array if it is enclosed in {...} since all the replacements are enclosed in {...}.

like image 35
anubhava Avatar answered Oct 31 '22 01:10

anubhava