6

I want to rid a text for repeated exclamation marks (!!!), question marks (??) or full stops (....) and replace them with a single instance of themselves. So I need "one preg_replace to rule them all" basically.

I currently have three separate patterns being executed:

preg_replace("/[!]{2,}/","!", $str);
preg_replace("/[?]{2,}/","?", $str);
preg_replace("/[.]{2,}/",".", $str);

Is there a way to replace the found character with a single instance of itself using just one regex pattern?

I need to turn:

Ok!!!
Really????
I guess.....

into:

Ok!
Really?
I guess.

With one regex pattern.

Hasen
  • 11,710
  • 23
  • 77
  • 135

2 Answers2

10

Use a capturing group with a backreference:

([?!.])\1+

Replace with $1.

See the regex demo.

Details

  • ([?!.]) - matches and captures into Group 1 a single char: ?, ! or .
  • \1+ - matches one or more instances of the content captured into Group 1.

PHP demo:

$str = "Ok!!!\nReally????\nI guess.....";
$res = preg_replace('/([?!.])\1+/', '$1', $str);
echo $res;

Results:

Ok!
Really?
I guess.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • That works great, thanks! For ages it wouldn't work for me but I found it only works with single quotes in the code? With double quotes the pattern didn't match for some reason. Anyway, its great. – Hasen Aug 28 '17 at 07:23
  • @Hasen: See the [Backreference does not work in PHP](https://stackoverflow.com/questions/30383383). Inside double quotes, you need to double the backslashes. – Wiktor Stribiżew Aug 28 '17 at 07:25
  • Oh I see...interesting. – Hasen Aug 28 '17 at 07:26
-1

Just for completion, I thought I'd post my own answer based on my original code after viewing the answer given by another.

 pattern ([!?.]){2,}

 preg_replace('/([!?.]){2,}/','$1', $str);

This pattern also seems to work fine.

Hasen
  • 11,710
  • 23
  • 77
  • 135
  • 1
    Be carefull, that doesn't do the same thing than other answer. This will replace `.!!.??` with `.` but may be is that what you want. – Toto Aug 28 '17 at 09:37