How to Split a String by Newline in JavaScript
A very common task in JavaScript is to take a block of multi-line text and split it into an array of individual lines. This is essential for processing text from a <textarea>, reading a file, or parsing data from an API response. The standard and most robust way to do this is with the String.prototype.split() method, using a regular expression to handle different types of line breaks.
This guide will teach you the correct regular expression to use for splitting by newline, and how to handle the common edge case of empty strings that can result from this operation.
The Core Problem: Different Operating Systems, Different Line Breaks
The main challenge when splitting by newline is that different operating systems use different characters to represent the end of a line:
- Unix/Linux/macOS:
\n(Line Feed or "LF") - Windows:
\r\n(Carriage Return + Line Feed or "CRLF")
If you only split by \n, your code will fail on text that comes from a Windows system, leaving unwanted \r characters in your array.
// Problem: This string has both Unix (LF) and Windows (CRLF) line endings.
const mixedLineBreaks = 'first line\nsecond line\r\nthird line';
// This is the WRONG way. It leaves a \r character behind.
const result = mixedLineBreaks.split('\n');
console.log(result);
// Output: [ 'first line', 'second line\r', 'third line' ] (This is incorrect!)
The Core Method: split() with a Regular Expression
The correct solution is to use a regular expression that accounts for both \n and \r\n.
Solution: the regex /\r?\n/ robustly handles both types of line endings.
const mixedLineBreaks = 'first line\nsecond line\r\nthird line';
const lines = mixedLineBreaks.split(/\r?\n/);
console.log(lines);
// Output: [ 'first line', 'second line', 'third line' ]
This is the standard, idiomatic way to split a string into an array of lines in JavaScript.
How the Regular Expression Works
Let's break down the pattern /\r?\n/:
/ ... /: These forward slashes mark the beginning and end of the regular expression.\r: This matches the "carriage return" character.?: This is a quantifier that means "zero or one" of the preceding character. So,\r?means "match a carriage return if it's there, but it's optional."\n: This matches the "line feed" character.
Together, the expression reads: "Split on a line feed \n, which may or may not be immediately preceded by a carriage return \r." This covers both \n and \r\n in a single, elegant pattern.
Handling a Common Edge Case: Trailing Newlines
A frequent issue is that a string might have a newline character at the very end. When you split by the newline, this results in an empty string ('') as the last element in your array.
// Problem: The trailing newline will create an extra empty string.
const strWithTrailingNewline = 'first\nsecond\n';
const lines = strWithTrailingNewline.split(/\r?\n/);
console.log(lines);
// Output: [ 'first', 'second', '' ] (The last element is often unwanted)
Solution: you can easily remove any empty strings from the resulting array by chaining the Array.prototype.filter() method with the Boolean constructor.
const strWithTrailingNewline = 'first\nsecond\n';
const lines = strWithTrailingNewline.split(/\r?\n/).filter(Boolean);
console.log(lines);
// Output: [ 'first', 'second' ]
How it Works
- The
filter(Boolean)trick is a concise and idiomatic way to remove "falsy" values from an array. In JavaScript, an empty string ('') is a falsy value. - The
Booleanconstructor converts each element to its boolean equivalent ('first'->true,''->false), andfilter()keeps only the elements that converted totrue.
Conclusion
Splitting a string by newline is a simple task if you use the correct, robust method.
- The recommended best practice is to use a regular expression that handles both Windows and Unix line endings:
string.split(/\r?\n/). - If you need to remove empty strings from the result (often caused by trailing newlines), chain the
filter()method for a clean and reliable output:string.split(/\r?\n/).filter(Boolean).
This approach is concise, efficient, and ensures your code will work correctly with text from any source.