Match linebreaks - \n or \r\n?

RegexLanguage AgnosticLine Breaks

Regex Problem Overview


While writing this answer, I had to match exclusively on linebreaks instead of using the s-flag (dotall - dot matches linebreaks).

The sites usually used to test regular expressions behave differently when trying to match on \n or \r\n.

I noticed

  • Regex101 matches linebreaks only on \n
    (example - delete \r and it matches)

  • RegExr matches linebreaks neither on \n nor on \r\n
    and I can't find something to make it match a linebreak, except for the m-flag and \s
    (example)

  • Debuggex behaves even more different:
    in this example it matches only on \r\n, while
    here it only matches on \n, with the same flags and engine specified

I'm fully aware of the m-flag (multiline - makes ^ match the start and $ the end of a line), but sometimes this is not an option. Same with \s, as it matches tabs and spaces, too.

My thought to use the unicode newline character (\u0085) wasn't successful, so:

  1. Is there a failsafe way to integrate the match on a linebreak (preferably regardless of the language used) into a regular expression?
  2. Why do the above mentioned sites behave differently (especially Debuggex, matching once only on \n and once only on \r\n)?

Regex Solutions


Solution 1 - Regex

I will answer in the opposite direction.

  1. For a full explanation about \r and \n I have to refer to this question, which is far more complete than I will post here: https://stackoverflow.com/questions/1761051/difference-between-n-and-r

Long story short, Linux uses \n for a new-line, Windows \r\n and old Macs \r. So there are multiple ways to write a newline. Your second tool (RegExr) does for example match on the single \r.

  1. [\r\n]+ as Ilya suggested will work, but will also match multiple consecutive new-lines. (\r\n|\r|\n) is more correct.

Solution 2 - Regex

In PCRE \R matches \n, \r and \r\n.

Solution 3 - Regex

You have different line endings in the example texts in Debuggex. What is especially interesting is that Debuggex seems to have identified which line ending style you used first, and it converts all additional line endings entered to that style.

I used Notepad++ to paste sample text in Unix and Windows format into Debuggex, and whichever I pasted first is what that session of Debuggex stuck with.

So, you should wash your text through your text editor before pasting it into Debuggex. Ensure that you're pasting the style you want. Debuggex defaults to Unix style (\n).

Also, NEL (\u0085) is something different entirely: https://en.wikipedia.org/wiki/Newline#Unicode

(\r?\n) will cover Unix and Windows. You'll need something more complex, like (\r\n|\r|\n), if you want to match old Mac too.

Solution 4 - Regex

This only applies to question 1.

I have an app that runs on Windows and uses a multi-line MFC editor box.
The editor box expects CRLF linebreaks, but I need to parse the text enterred
with some really big/nasty regexs'.

I didn't want to be stressing about this while writing the regex, so
I ended up normalizing back and forth between the parser and editor so that
the regexs' just use \n. I also trap paste operations and convert them for the boxes.

This does not take much time.
This is what I use.

 boost::regex  CRLFCRtoLF (
 	 " \\r\\n | \\r(?!\\n) "
 	 , MODx);
 
 boost::regex  CRLFCRtoCRLF (
 	 " \\r\\n?+ | \\n "
 	 , MODx);
 
 
 // Convert (All style) linebreaks to linefeeds 
 // ---------------------------------------
 void ReplaceCRLFCRtoLF( string& strSrc, string& strDest )
 {
 	strDest  = boost::regex_replace ( strSrc, CRLFCRtoLF, "\\n" );
 }
 
 // Convert linefeeds to linebreaks (Windows) 
 // ---------------------------------------
 void ReplaceCRLFCRtoCRLF( string& strSrc, string& strDest )
 {
 	strDest  = boost::regex_replace ( strSrc, CRLFCRtoCRLF, "\\r\\n" );
 }
 

Solution 5 - Regex

In Python:

# as Peter van der Wal's answer
re.split(r'\r\n|\r|\n', text, flags=re.M) 

or more rigorous:

# https://docs.python.org/3/library/stdtypes.html#str.splitlines
str.splitlines()

Solution 6 - Regex

A bit late to the party, but for the rest could be perhaps useful. In javascript you can simply write pipe (|) to match the newlines/linebreaks as well. In my case I needed to get rid of all the commas, semicolons and whitespace characters (linebreaks included) so I ended up using this:

.split(/[\s,;|]+/)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKeyNoneView Question on Stackoverflow
Solution 1 - RegexPeter van der WalView Answer on Stackoverflow
Solution 2 - RegexCwazy PavingView Answer on Stackoverflow
Solution 3 - RegexDaneView Answer on Stackoverflow
Solution 4 - Regexuser557597View Answer on Stackoverflow
Solution 5 - RegexKeelungView Answer on Stackoverflow
Solution 6 - RegexKepiView Answer on Stackoverflow