3

I use this function to remove three dots before or after a newline:

private function trimThreeDots(string $text): string {
    $threeDotsAtTheBeginning = '((^|[\n]{1})[\\.]{3})';
    $threeDotsAtTheEnd = '([\\.]{3}[\n]{1})';

    $pattern = '/' . $threeDotsAtTheBeginning . '|' . $threeDotsAtTheEnd . '/';

    return preg_replace_callback($pattern, function ($str) {
        return str_replace("...", "", $str[0]);
    }, $text);
}

It works, except that in case that I have a string like this one:

"Bla bla bla...
...bla bla bla"

I only get a single match. But I want to get two matches, because I need to remove both occurrences of three dots. I wonder if maybe there is a more straightforward and efficient way to write this regex and getting two matches in the above case?

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
  • You don't need regex, just put the newline character in your `str_replace()` source string. – Alex Howansky Oct 15 '18 at 13:46
  • Without regex I would consider splitting into lines, `trim()` the dots, and re-join if necessary. – Andy G Oct 15 '18 at 13:50
  • @AndyG `trim()` won't do the job. The second argument is a list of characters to trim. See [this](https://stackoverflow.com/questions/50174181/why-does-ltrim-remove-one-character-when-the-second-argument-contains-an-operato/50174338#50174338) – Cid Oct 15 '18 at 14:00
  • The list could just contain a single character, a dot. – Andy G Oct 15 '18 at 14:09
  • This will remove any number of leading/trailing dots. Try this `echo trim("bla bla bla.......", '.');` – Cid Oct 15 '18 at 14:16
  • @Cid Yes, I was assuming just a sequence of dots, not stressing the need to remove explicitly three of them. But I'm not necessarily trying to present an alternative solution, just a comment that regex might be overkill for such a task. – Andy G Oct 15 '18 at 14:23

3 Answers3

5

You may use

$s = "Bla bla bla...
...bla bla bla";
echo preg_replace('~(?:\.{3})?(\R)(?:\.{3})?~', '$1', $s);

See the PHP demo and a regex demo.

Details

  • (?:\.{3})? - an optional sequence of 3 dots
  • (\R) - Group 1: any line break sequence
  • (?:\.{3})? - an optional sequence of 3 dots

The $1 replacement replaces the match with the exact line break sequence the regex matches.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Didn't need the "\h*" because I am not removing the three dots in case that there is a space after or before a newline. But the rest is ok, thanks. – Ramy Al Zuhouri Oct 15 '18 at 13:54
  • @RamyAlZuhouri Then why use `\s*` in your `'([\\.]{3}[\s]*[\n]{1})'` pattern? Ok, since that was your pattern error, I removed the `\h*` part. – Wiktor Stribiżew Oct 15 '18 at 13:55
2

You can use the RegEx \.{3}(?=\n)|(?<=\n)\.{3}

  • \.{3}(?=\n) matches the case where the newline is after the dots

  • (?<=\n)\.{3} matches the case where the newline is before the dots

Demo.


PHP:

preg_replace('~\.{3}(?=\n)|(?<=\n)\.{3}~', '', $s);
Zenoo
  • 12,670
  • 4
  • 45
  • 69
0

Seems overly complex maybe? What about this?

$re = '/(^\.{3}|\.{3}$)/gm';
$str = 'Bla bla bla...
...bla bla bla';
$subst = '';

$result = preg_replace($re, $subst, $str);

echo "The result of the substitution is ".$result;
springbo
  • 1,096
  • 1
  • 9
  • 15