1

I have this string

$string = "some words and then #1.7 1.7 1_7 and 1-7";

and I would like that #1.7/1.7/1_7 and 1-7 to be replaced by S1E07.
Of course, instead of "1.7" is just an example, it could be "3.15" for example.

I managed to create the regular expression that would match the above 4 variants

/\#\d{1,2}\.\d{1,2}|\d{1,2}_\d{1,2}|\d{1,2}-\d{1,2}|\d{1,2}\.\d{1,2}/

but I cannot figure out how to use preg_replace (or something similar?) to actually replace the matches so they end up like S1E07

2
  • You need to provide more explicit information regarding the format of possible inputs, and exactly how those inputs effect the output. Will it always be 1 and 7, or could it be different numbers (or different length of numbers, i.e. something like 23.456)? Is the output based on those values, and if so, is the 7 supposed to be padding with a leading 0 when it's less than 10? Commented Sep 21, 2012 at 10:27
  • numbers can be from 1 to 99 so it can be 1.1 to 99.99. padding would be nice but not a must. Commented Sep 21, 2012 at 10:33

4 Answers 4

3

You need to use preg_replace_callback if you need to pad 0 if the number less than 10.

$string = "some words and then #1.7 1.7 1_7 and 1-7";
$string = preg_replace_callback('/#?(\d+)[._-](\d+)/', function($matches) {
  return 'S'.$matches[1].'E'.($matches[2] < 10 ? '0'.$matches[2] : $matches[2]);
}, $string);
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! Your regular expression is surely more elegant than mine and the results are those expected the only thing is that it will also match stuff like 1999.12 which I wouldn't want. I tried with \d{1,2} but I would get back 19S99E12
Using word boundaries \b you should be able to achieve this. Check my answer out. It's tested and works.
yes, your answer works and is almost perfect it is just that if I use \b this way /\b#?(\d{1,2})[._-](\d{1,2})/ I'll get #S1E07
My bad put the word boundary after the #? and you're all set. Like #?\b(\d...
2

You could use this simple string replace:

preg_replace('/#?\b(\d{1,2})[-._](\d{1,2})\b/', 'S${1}E${2}', $string);

But it would not yield zero-padded numbers for the episode number:

// some words and then S1E7 S1E7 S1E7 and S1E7

You would have to use the evaluation modifier:

preg_replace('/#?\b(\d{1,2})[-._](\d{1,2})\b/e', '"S".str_pad($1, 2, "0", STR_PAD_LEFT)."E".str_pad($2, 2, "0", STR_PAD_LEFT)', $string);

...and use str_pad to add the zeroes.

// some words and then S01E07 S01E07 S01E07 and S01E07

If you don't want the season number to be padded you can just take out the first str_pad call.

Comments

1

I believe this will do what you want it to...

/\#?([0-9]+)[._-]([0-9]+)/

In other words...

  • \#? - can start with the #
  • ([0-9]+) - capture at least one digit
  • [._-] - look for one ., _ or -
  • ([0-9]+) - capture at least one digit

And then you can use this to replace...

S$1E$2

Which will put out S then the first captured group, then E then the second captured group

Comments

1

You need to put brackets around the parts you want to reuse ==> capture them. Then you can access those values in the replacement string with $1 (or ${1} if the groups exceed 9) for the first group, $2 for the second one...

The problem here is that you would end up with $1 - $8, so I would rewrite the expression into something like this:

/#?(\d{1,2})[._-](\d{1,2})/

and replace with

S${1}E${2}

I tested it on writecodeonline.com:

$string = "some words and then #1.7 1.7 1_7 and 1-7";
$result = preg_replace('/#?(\d{1,2})[._-](\d{1,2})/', 'S${1}E${2}', $string);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.