/^/
EasyText Processing4 min read

Line Ending (Newline) Regex

Matches a single line ending in any common style: Windows CRLF (\r\n), classic Mac CR (\r), or Unix LF (\n).

#whitespace#text-processing#newline#line-endings#formatting

Regex Pattern

\r\n|\r|\n

Default flags: g

Pattern Breakdown

Hover over a token to see what it does.

\r\n|\r|\n
TokenMeaning
\r\nWindows-style line ending: carriage return followed by line feed
\rClassic Mac OS-style line ending: a lone carriage return
\nUnix/Linux/modern macOS-style line ending: a lone line feed
|Alternation, tried left to right so the two-character CRLF sequence is checked before the single-character fallbacks

Detailed Explanation

What it does

This pattern matches exactly one line-ending sequence, correctly treating a Windows CRLF pair as a single unit rather than as two separate line breaks. It's designed to normalize or split text that may have originated from different operating systems.

Why it works

The alternation is ordered so the two-character \r\n sequence is attempted first; if it matched \r or \n alone before the pair, a Windows-style CRLF file would be seen as two line breaks per line instead of one. Placing the longer alternative first ensures each line ending is consumed as a single, correct match regardless of source platform.

Common use cases

  • Normalizing mixed line endings to a single style (e.g. always \n) before further processing
  • Splitting a multi-line string into individual lines regardless of its origin platform
  • Counting the number of lines in a file that may have been edited on multiple operating systems
  • Detecting whether a text file uses CRLF, LF, or a mix of both

Edge cases

  • A Windows CRLF pair, '\r\n', is matched as one single line ending, not two
  • A lone carriage return, '\r', from old classic Mac files is matched as its own line ending
  • A lone line feed, '\n', the standard on Unix-like systems, is matched directly
  • A string with no line breaks at all never matches, correctly signaling single-line content

Limitations

  • This pattern does not detect other Unicode line-separator characters like U+2028 (Line Separator) or U+0085 (Next Line)
  • It treats all matched line endings the same when just testing for presence; distinguishing which style was used requires capturing which alternative matched
  • Splitting on this pattern discards the line-ending information, so re-joining lines requires deciding on a style explicitly

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

a b a b a b
5 matches

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Fail
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const newlineRegex = /\r\n|\r|\n/g;
const lines = 'line1\r\nline2\nline3'.split(newlineRegex);

Common Mistakes

Ordering the alternation as \n|\r|\r\n, which lets the single-character \r match consume half of a CRLF pair before the full pair is tried

Fix: Always put the longer \r\n alternative first so it's matched before the single-character fallbacks

Using only \n to split lines, which leaves a trailing \r on every line of a CRLF-formatted file

Fix: Use the combined \r\n|\r|\n pattern (or a library's universal-newline mode) to handle all common line-ending styles

Assuming split() on this pattern preserves which line-ending style each line originally had

Fix: If the original style matters, capture it separately (e.g. with match() before splitting) rather than relying on split() output

Performance Notes

  • The alternation has only three simple branches, so matching remains linear in the length of the input with no catastrophic backtracking risk
  • Ordering the longer alternative (\r\n) first avoids wasted partial matches and keeps line-ending detection correct and efficient
  • For very large files, prefer a streaming line-reader over loading the entire file into memory just to normalize line endings

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes