How to replace one or two consecutive line breaks in a string?

I’m developing a single serving site in PHP that simply displays messages that are posted by visitors (ideally surrounding the topic of the website). Anyone can post up to three messages an hour.

Since the website will only be one page, I’d like to control the vertical length of each message. However, I do want to at least partially preserve line breaks in the original message. A compromise would be to allow for two line breaks, but if there are more than two, then replace them with a total of two line breaks in a row. Stack Overflow implements this.

For example:

Porcupines\nare\n\n\n\nporcupiney.

would be changed to

Porcupines<br />are<br /><br />porcupiney.

One tricky aspect of checking for line breaks is the possibility of their being collected and stored as \r\n, \r, or \n. I thought about converting all line breaks to <br />s using nl2br(), but that seemed unnecessary.

My question: Using regular expressions in PHP (with functions like preg_match() and preg_replace()), how can I check for instances of more than two line breaks in a row (with or without blank space between them) and then change them to a total of two line breaks?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

preg_replace('/(?:(?:\r\n|\r|\n)\s*){2}/s', "\n\n", $text)

Solution 2

Something like

preg_replace('/(\r|\n|\r\n){2,}/', '<br/><br/>', $text);

should work, I think. Though I don’t remember PHP syntax exactly, it might need some more escaping :-/

Solution 3

\R is the system-agnostic escape sequence which will match \n, \r and \r\n.

Because you want to greedily match 1 or 2 consecutive newlines, you will need to use a limiting quantifier {1,2}.

Code: (Demo)

$string = "Porcupines\nare\n\n\n\nporcupiney.";

echo preg_replace('~\R{1,2}~', '<br />', $string);

Output:

Porcupines<br >are<br /><br />porcupiney.

Now, to clarify why/where the other answers are incorrect…

@DavidZ’s unexplained answer fails to replace the lone newline character (Demo of failure) because of the incorrect quantifier expression.

It generates:

Porcupines\nare<br/><br/>porcupiney.

The exact same result can be generated by @chaos’s code-only answer (Demo of failure). Not only is the regular expression long-winded and incorrectly implementing the quantifier logic, it is also adding the s pattern modifier.

The s pattern modifier only has an effect on the regular expression if there is a dot metacharacter in the pattern. Because there is no . in the pattern, the modifier is useless and is teaching researchers meaningless/incorrect coding practices.

Solution 4

I just wanted to add to this, even though it doesnt directly answer the question, it may help someone who is wanting to limit the number of line breaks.
I needed this to limit the number of line breaks in forum posts. I used the selected answer above, and added this:

//Some pre processing
$textarea_reply = str_replace("\r", "<br>", $textarea_reply);
$textarea_reply_splitByLines = explode("<br>", $textarea_reply);
$textarea_reply = "";
$line_count = 0;
$line_limit = 10;

//Re-add the line breaks with a limit of $line_limit
foreach ($textarea_reply_splitByLines as $line){
    $textarea_reply.= $line." "; 
    if($line_count<$line_limit) $textarea_reply.= "<br>";
    $line_count++;
}

This limits the number of line breaks to a maximum amount no matter what.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply