Question

This is probably an easy one, but I couldn't figure it out after searching. I managed to alter the output 20 different ways, but none of them were what I want from it =D

<?php

$text = <<<DATA
Show.Name.2x05.HDTV.x264
Show.Name.2x06.HDTV.x264
Show.Name.2x07.HDTV.x264
Show.Name.2x08.HDTV.x264
Show.Name.2x09.HDTV.x264
DATA;

$text = preg_replace('/([0-9]{1,2})x([0-9]{2})/e',
                 'sprintf("S%02dE%02d", $1, $2)', $text);
echo $text;
?>

Output

Show.Name.S02E05.HDTV.x264
Show.Name.S02E06.HDTV.x264
Show.Name.S02E07.HDTV.x264
Show.Name.S02E00.HDTV.x264
Show.Name.S02E00.HDTV.x264

As you can see it turns my 08 and 09 into 00, my best guess is this is related to PHP thinking I'm trying to indicate octal, as it is a base8 system it only likes 0-7. I didn't think a leading zero in a "string" would indicate that though? How can I alter my code to accept 08 and 09 but not change them to 00? I tried a few ways to try and escape it but i'm stuck.

Was it helpful?

Solution

Currently what you are doing is: sprintf("S%02dE%02d", 2, 05) which is using octal. You're getting octal results because you need to treat the numbers with leading zeros as strings before you parse them rather than execute them directly. Thus the easy solution which you were seeking is simply to quote them like so:

$text = preg_replace('/([0-9]{1,2})x([0-9]{2})/e',
    'sprintf("S%02dE%02d", "$1", "$2")', $text);

Alternatively, since the e flag is depreciated, try using preg_replace_callback which is easier to work with:

$text = preg_replace_callback('/([0-9]{1,2})[x]([0-9]{2})/',
    function($matches){return sprintf("S%02dE%02d", $matches[1], $matches[2]);}
, $text);

OTHER TIPS

Try this instead using preg_replace_callback—since the e modifier for preg_replace is now deprecaiated—and str_pad:

$text = <<<DATA
Show.Name.2x05.HDTV.x264
Show.Name.2x06.HDTV.x264
Show.Name.2x07.HDTV.x264
Show.Name.2x08.HDTV.x264
Show.Name.2x09.HDTV.x264
DATA;

$text = preg_replace_callback('/([0-9]{1,2})x([0-9]{2})/', function($matches) {
  return 'S'.(str_pad($matches[1], 2, 0, STR_PAD_LEFT)).'E'.(str_pad($matches[2], 2, 0, STR_PAD_LEFT));
}, $text);

echo '<pre>';
echo $text;
echo '</pre>';

And the output is:

Show.Name.S02E05.HDTV.x264
Show.Name.S02E06.HDTV.x264
Show.Name.S02E07.HDTV.x264
Show.Name.S02E08.HDTV.x264
Show.Name.S02E09.HDTV.x264

Keeping with your code

<?php

$text = <<<DATA
Show.Name.2x05.HDTV.x264
Show.Name.2x06.HDTV.x264
Show.Name.2x07.HDTV.x264
Show.Name.2x08.HDTV.x264
Show.Name.2x09.HDTV.x264
DATA;

$text = preg_replace('/(\\\\.[0-9]{1,2})(x[0-9]{2})/e',
                 'sprintf("S%02dE%02d", ltrim($1,\'.\', ltrim($2,\'x\'))', $text);
echo $text;
?>

Works

But as others have suggested, the /e modifier is deprecated.

The reason this happens is due to the $2 (and the $1 but its not seen in your example) variable starting with a 0 and being treated as octal from the php manual

http://www.php.net/manual/en/language.types.integer.php

edit: Ultimater answer is much better

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top