0

I have a string that represents a day of the week "U", "M", "T", etc". I'm trying to use preg_replace to replace the letter with the actual day name, like Sunday, Monday, etc.

However, it appears to be applying the array of replacements in an iterative fashion, which isn't what the documentation appears to specify. Any ideas?

$input = "U";
$nice_day_name = preg_replace(['/U/','/M/','/T/','/W/','/R/','/F/','/S/'],
   ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
   $input);

// Outputs "Satun", should be "Sun"
frodo2975
  • 10,340
  • 3
  • 34
  • 41
  • 3
    Why do you need `preg_replace()` for this at all? You are just searching for known strings so `str_replace()` should work just fine. Or if you always have a single character input, why not specify an associative array to map the replacements? – Mike Brant Mar 31 '14 at 17:51
  • 1
    Well, an obvious workaround is to prevent replacing the parts of text that's already replaced - by changing `/T/` for `/T(?!ue|hu)/`, for example. As for the order of processing - well, what else would you expect, without creating potential conflicts? – raina77ow Mar 31 '14 at 17:52
  • *If subject is an array, then the search and replace is performed on every entry of subject* – JBES Mar 31 '14 at 17:52
  • @MikeBrant: Nope, [`str_replace()` wouldn't work either](http://stackoverflow.com/a/22575151/1438393). – Amal Murali Mar 31 '14 at 17:54
  • @raina77ow Negative lookaheads are anything but obvious :p – Niet the Dark Absol Mar 31 '14 at 18:04

4 Answers4

3

The documentation seems to be ambiguous. Here's what it says on the subject:

If both pattern and replacement parameters are arrays, each pattern will be replaced by the replacement counterpart.

It looks like you're reading this as "the original string will be checked for each pattern in the array, and the replacement will be made". I can see how one would read it that way. What it seems to be doing instead is checking each pattern against the string, including any replacements already made.

So it's doing this:

  1. Check the first pattern, /U/, find a match, make the replacement --> Sun
  2. Check a bunch more, find no match
  3. Check the last one, /S/, find a match (the first character), make the replacement --> Satun

To fix this, you can include the start/end character in each pattern:

['/^U$/','/^M$/','/^T$/','/^W$/','/^R$/','/^F$/','/^S$/']

This will result in a match only if the string is one character long.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
Kryten
  • 15,230
  • 6
  • 45
  • 68
2

This task is better accomplished using strtr:

$replacements = [
    "U"=>"Sun",
    "M"=>"Mon",
    "T"=>"Tue",
    "W"=>"Wed",
    "R"=>"Thu",
    "F"=>"Fri",
    "S"=>"Sat"
];
$nice_day_name = strtr($input,$replacements);
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
2

Don't make the problem harder than it should be:

$day_names = array_combine(
    ['U','M','T','W','R','F','S'],
    ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
);

$nice_day_name = $day_names[$input];

str_replace() has the same issue, and I cover this in my answer to a different question.

Live demo

Community
  • 1
  • 1
Amal Murali
  • 75,622
  • 18
  • 128
  • 150
0

Try this:

$string = 'U';
$trans = array("U" => "Sun", "M" => "Mon", "T" => "Tue", "W" => "Wed", "R" => "Thu",
 "F" => "Fri", "S" => "Sat");
$result = strtr($string,$trans);
echo $result;
  • Just a note: this was already suggested by Niet, [in his answer here](http://stackoverflow.com/a/22768816/1438393). – Amal Murali Mar 31 '14 at 18:10
  • Oh yes actually it was not available when I started typing and then I tested and posted which took a little time.. –  Mar 31 '14 at 18:27