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?

2
  • YoYoMa's comment: "Apparently some have missed this warning @ 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." Commented Feb 14, 2012 at 20:17
  • 2
    @powtac The goal is "bl[aoieu]?ck" it's a good question! Commented Mar 21, 2013 at 18:40

7 Answers 7

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');
Sign up to request clarification or add additional context in comments.

4 Comments

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.
What problems are you talking about? Performance problems, debugging problems, 'bad programmer == bad code' problems or something else?
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.
same problem here but. trying to use the function but not sure what i should be adding for the 2nd variable currently '[aoieu]?'?
4

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]?'));

Comments

3

You might want to try this

<?php
$string = 'black';
$pattern = '/([aeiou])/i';
$replacement = '[aeiou]';
echo preg_replace($pattern, $replacement, $string);
?>

Comments

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.

Comments

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

4 Comments

Fails when you have a ~ in the input. Trivial reason that this is not a robust solution.
You cannot "find another pattern which does not occur" in the general case. And you should prove that it'll be fastest if you want to assert that!
It won't be fastest probably, but using a weird character like ¯ or œ might do the trick.
google.com/search?q=str_replace+vs.+preg_replace lot of benchmarks for str_replace vs. preg_replace out there.
0

Here it is:

$output = preg_replace('/[aeiou]/', '[aeiou]?', $input);

Comments

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 ) );

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.