6

I need to replace every occurrence of one of the letters a,o,i,e,u with [aoieu]?
I tried to do the following:

str_replace(array('a', 'o', 'i', 'e', 'u'), '[aoieu]?', $input);

But when giving it input of black instead of giving me the expected bl[aoieu]?ck it gave me

bl[a[ao[aoi[aoie[aoieu]?]?[aoieu]?]?[aoie[aoieu]?]?[aoieu]?]?[aoi[aoie[aoieu]?]?[aoieu]?]?[aoie[aoieu]?]?[aoieu]?]?ck

How can I get it to not replace things it already replaced?

Daniel
  • 30,896
  • 18
  • 85
  • 139
  • YoYoMa's comment: "Apparently some have missed this warning @ http://us3.php.net/manual/en/function.str-replace.php Caution Replacement order gotcha Because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements. See also the examples in this document. Others have answered the question with possible solutions to the problem. This is why the problem is occurring." – Peter O. Feb 14 '12 at 20:17
  • 2
    @powtac The goal is "bl[aoieu]?ck" it's a good question! – PJ Brunet Mar 21 '13 at 18:40

7 Answers7

5

You can consider using a regular expression for this, or you can make your own function which steps through the string one letter at a time. Here's a regex solution:

preg_replace('/[aoieu]/', '[aoieu]?', $input);

Or your own function (note that $search only can be a single char or an array of chars, not strings - you can use strpos or similar to build one which handles longer strings as well):

function safe_replace($search, $replace, $subject) {
  if(!is_array($search)) {
    $search = array($search);
  }
  $result = '';
  $len = strlen($subject);
  for($i = 0; $i < $len; $i++) {
    $c = $subject[$i];
    if(in_array($c, $search)) {
      $c = $replace;
    }
    $result .= $c;
  }
  return $result;
}
//Used like this:
safe_replace(array('a', 'o', 'i', 'e', 'u'), '[aoieu]?', 'black');
Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
  • The regexp one is working. about the second one, I'm not a fan of 'do it your own' after all the problems it can do with coding, especially with interpreted language. – Daniel Aug 11 '11 at 13:41
  • What problems are you talking about? Performance problems, debugging problems, 'bad programmer == bad code' problems or something else? – Emil Vikström Aug 11 '11 at 13:46
  • 1
    the kind of problems when you implement something thats already implemented - a bunch of useless code. also there are performance issues, string manipulation is slow in non native code. – Daniel Aug 11 '11 at 14:12
  • same problem here but. trying to use the function but not sure what i should be adding for the 2nd variable currently '[aoieu]?'? – v3nt Sep 18 '12 at 12:30
3

You might want to try this

<?php
$string = 'black';
$pattern = '/([aeiou])/i';
$replacement = '[aeiou]';
echo preg_replace($pattern, $replacement, $string);
?>
az4dan
  • 651
  • 2
  • 10
  • 30
3

Taken from the documentation:

Replacement order gotcha

Because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements.

powtac
  • 40,542
  • 28
  • 115
  • 170
3

I recommend avoiding preglike functions and using strtr().

This native function

  • makes a single pass over the input string,
  • does not replace replacements, and
  • finds the longest matching substring to replace (when a qualifying string is found within another qualifying string)

Code:

$result = strtr($input, array('a' => '[aoieu]?', 
                         'o' => '[aoieu]?', 
                         'i' => '[aoieu]?', 
                         'e' => '[aoieu]?', 
                         'u' => '[aoieu]?'));
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Nemanja
  • 1,505
  • 12
  • 24
0
$input = str_replace(array('a', 'o', 'i', 'e', 'u'),   '~',          $input);
$input = str_replace('~',                              '[aoieu]?',   $input);
powtac
  • 40,542
  • 28
  • 115
  • 170
0

Here it is:

$output = preg_replace('/[aeiou]/', '[aeiou]?', $input);
Samnan
  • 653
  • 1
  • 5
  • 13
0

You might be able to get preg_replace to handle this for you (see Thax, Emil, etc.'s answers). Otherwise, if that is too complicated, you can, tokenize:

$token = '{{{}}}';
// replace the temporary value with the final value
str_replace( $token, '[aoieu]?', 
    // replace all occurances of the string with a temporary value.
    str_replace( (array('a', 'o', 'i', 'e', 'u'), $token, $input ) );
cwallenpoole
  • 79,954
  • 26
  • 128
  • 166