2

I need to parse a string and replace a specific format for tv show names that don't fit my normal format of my media player's queue.

Some examples

Show.Name.2x01.HDTV.x264 should be Show.Name.S02E01.HDTV.x264
Show.Name.10x05.HDTV.XviD should be Show.Name.S10E05.HDTV.XviD

After the show name, there may be 1 or 2 digits before the x, I want the output to always be an S with two digits so add a leading zero if needed. After the x it should always be an E with two digits.

I looked through the manual pages for the preg_replace, split and match functions but couldn't quite figure out what I should do here. I can match the part of the string I want with /\dx\d{2}/ so I was thinking first check if the string has that pattern, then try and figure out how to split the parts out of the match but I didn't get anywhere.

I work best with examples, so if you can point me in the right direction with one that would be great. My only test area right now is a PHP 4 install, so please no PHP 5 specific directions, once I understand whats happening I can probably update it later for PHP 5 if needed :)

  • `please no PHP 5 specific directions` -- Why not? Why are you using an ancient PHP version? Why don't you want to upgrade to a more recent version? – Amal Murali Oct 26 '13 at 06:03
  • My media server runs its own php4 back end which I am not looking to mess with right now. That's an issue for another time =/ – frozenthorn Oct 26 '13 at 06:19
  • What have you tried? Show us some code, please. No one is going to install PHP 4 and do the work for you. – Sverri M. Olsen Oct 26 '13 at 06:39
  • I wouldn't ask anyone to, the various code examples provided all seem to function to the goal so its exactly what I asked for. – frozenthorn Oct 26 '13 at 07:12

3 Answers3

1

preg_replace is the function you are looking function.

You have to write a regex pattern that picks correct place.

  <?php
  $replaced_data = preg_replace("~([0-9]{2})x([0-9]{2})~s", "S$1E$2", $data);
  $replaced_data = preg_replace("~S([1-9]{1})E~s", "S0$1E", $replaced_data);
  ?>

Sorry I could not test it but it should work.

Valour
  • 773
  • 10
  • 32
  • There are no letters in your regex, so the `i` modifier is not needed. You also do not use any `.` metacharacter in the regex, which means that the `s` modifier is not needed either. Also, the replacing does not handle leading `0`s, which the questioner clearly stated they would like to see. – Sverri M. Olsen Oct 26 '13 at 06:14
  • I modified the pattern. – Valour Oct 26 '13 at 06:19
  • Why do you use the `s` modifier?! It only has an effect if you use the `.` metacharacter. You do not use it in your regexes. It is not needed. Also, `[1-9]{1}` is *exactly the same* as `[1-9]`. There is no need to explicitly say that there is only one of something; it is implied. – Sverri M. Olsen Oct 26 '13 at 06:28
  • @SverriM.Olsen: You forget the `x` letter. – Casimir et Hippolyte Oct 26 '13 at 06:29
  • @CasimiretHippolyte Yeah, I missed that. Using `[xX]` should suffice, though. I have never seen a capital X in the episode/season part of a TV show file name, however, but they could occur so better to be on the safe side. – Sverri M. Olsen Oct 26 '13 at 06:45
  • Thanks for all the help! I've looked up the different parts of the solution and have a much better understanding of whats going on now, much appreciated. – frozenthorn Oct 26 '13 at 07:31
1

An other way using the preg_replace_callback() function:

$subject = <<<'LOD'
Show.Name.2x01.HDTV.x264 should be Show.Name.S02E01.HDTV.x264
Show.Name.10x05.HDTV.XviD should be Show.Name.S10E05.HDTV.XviD
LOD;

$pattern = '~([0-9]++)x([0-9]++)~i';
$callback = function ($match) {
    return sprintf("S%02sE%02s", $match[1], $match[2]);
};

$result = preg_replace_callback($pattern, $callback, $subject);

print_r($result);
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
1

A different approach as a solution using #sprintf using PHP4 and below.

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

Note: The use of the e modifier is depreciated as of PHP5.5, so use preg_replace_callback()

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

Output

Show.Name.S02E01.HDTV.x264
Show.Name.S10E05.HDTV.XviD

See working demo

hwnd
  • 69,796
  • 4
  • 95
  • 132
  • This definitely seems to be the shortest route to the goal, one function with all the required aspects, thanks for the additional solution :) – frozenthorn Oct 26 '13 at 07:13
  • You should avoid the use of the `e` modifier -- [it's deprecated as of PHP 5.5.0](http://php.net/manual/en/reference.pcre.pattern.modifiers.php). Check [this awesome post](http://stackoverflow.com/questions/3115559/exploitable-php-functions). Use [`preg_replace_callback()`](http://php.net/preg-replace-callback) instead. – HamZa Oct 26 '13 at 12:41