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.

Était-ce utile?

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

Autres conseils

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top