192

Within Node, how do I split a string using newline ('\n') ? I have a simple string like var a = "test.js\nagain.js" and I need to get ["test.js", "again.js"]. I tried

a.split("\n");
a.split("\\n");
a.split("\r\n");
a.split("\r");

but the above doesn't work.

d-cubed
  • 1,034
  • 5
  • 30
  • 58
PaolaJ.
  • 10,872
  • 22
  • 73
  • 111
  • possible duplicate of [JavaScript string newline character?](http://stackoverflow.com/questions/1155678/javascript-string-newline-character) – Mene Feb 20 '14 at 00:28
  • 11
    [`split()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split) doesn't modify the original string. – thgaskell Feb 20 '14 at 02:19
  • This looks like a pure JavaScript question, not requiring a node.js tag. – Wyck Jan 29 '20 at 15:36
  • @Wyck, it's useful to know that Node is the intended runtime, because the `newline` character in a string is often platform-dependent. In Node.js, it's very common to operate on file texts with `newline` characters, and it's important to know the platform. In a browser context, this this less of an issue. But I would suggest the OP change the question to specify the target environment, or else ask for solutions that work generically on all major platforms. – Austin Davis Sep 07 '20 at 01:42

7 Answers7

331

Try splitting on a regex like /\r?\n/ to be usable by both Windows and UNIX systems.

> "a\nb\r\nc".split(/\r?\n/)
[ 'a', 'b', 'c' ]
maerics
  • 151,642
  • 46
  • 269
  • 291
  • 4
    What about classic Macs? ;) – AshleyF Nov 07 '15 at 00:03
  • 15
    classic Macs died along with Steve Jobs... sadness :( – ymz Jun 15 '17 at 19:23
  • 63
    to catch \n, \r and \r\n: `split(/[\r\n]+/)` – Julian TF Jul 26 '17 at 10:15
  • 2
    MacOSX don't use single \r anymore, that was only for old Macs. I think they have the same \n as other unixes. – jcubic Dec 10 '17 at 09:10
  • How can .split(/\r?\n/) be changed to support any number of "\r\n" or "\n"? In other words if I have a string "The\r\n\r\nquick\r\n\r\nbrown\r\nfox\r\njumps\r\n\r\nover" how to change regex above to get just [quick, brown, fox, jumps, over]? – Neal Davis Mar 28 '18 at 22:00
  • I just tried .split(/[\r?\n]+/) and that seems to work for splitting if you have multiple consecutive line breaks such as "\r\n\r\n..." or "\n\n..." - hope I got that correct. – Neal Davis Mar 28 '18 at 22:18
  • 2
    You don't need the `?`. `[\r\n]` is a regex *character set*, which means it can match `\r` or `\n`. `split(/[\r\n]+/)` would work. –  Jun 10 '18 at 22:32
  • 21
    /[\r\n]+/ will filter out empty lines – Spongman Jul 07 '18 at 18:44
64

If the file is native to your system (certainly no guarantees of that), then Node can help you out:

var os = require('os');

a.split(os.EOL);

This is usually more useful for constructing output strings from Node though, for platform portability.

qubyte
  • 17,558
  • 3
  • 30
  • 32
56

It looks like regex /\r\n|\r|\n/ handles CR, LF, and CRLF line endings, their mixed sequences, and keeps all the empty lines inbetween. Try that!

    function splitLines(t) { return t.split(/\r\n|\r|\n/); }

    // single newlines
    console.log(splitLines("AAA\rBBB\nCCC\r\nDDD"));
    // double newlines
    console.log(splitLines("EEE\r\rFFF\n\nGGG\r\n\r\nHHH"));
    // mixed sequences
    console.log(splitLines("III\n\r\nJJJ\r\r\nKKK\r\n\nLLL\r\n\rMMM"));

You should get these arrays as a result:

[ "AAA", "BBB", "CCC", "DDD" ]
[ "EEE", "", "FFF", "", "GGG", "", "HHH" ]
[ "III", "", "JJJ", "", "KKK", "", "LLL", "", "MMM" ]

You can also teach that regex to recognize other legit Unicode line terminators by adding |\xHH or |\uHHHH parts, where H's are hexadecimal digits of the additional terminator character codepoint (as seen in Wikipedia article as U+HHHH).

Ran Marciano
  • 1,431
  • 5
  • 13
  • 30
blakkwater
  • 1,133
  • 7
  • 13
41
a = a.split("\n");

Note that splitting returns the new array, rather than just assigning it to the original string. You need to explicitly store it in a variable.

Charlie Harding
  • 653
  • 8
  • 22
alex
  • 11,935
  • 3
  • 30
  • 42
21

A solution that works with all possible line endings including mixed ones and keeping empty lines as well can be achieved using two replaces and one split as follows

text.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/);

some code to test it

  var CR = "\x0D";  //   \r
  var LF = "\x0A";  //   \n

  var mixedfile = "00" + CR + LF +            // 1 x win
                  "01" + LF +                 // 1 x linux
                  "02" + CR +                 // 1 x old mac
                  "03" + CR + CR +            // 2 x old mac
                  "05" + LF + LF +            // 2 x linux
                  "07" + CR + LF + CR + LF +  // 2 x win
                  "09";

  function showarr (desc, arr)
  {
     console.log ("// ----- " + desc);
     for (var ii in arr)
        console.log (ii + ") [" + arr[ii] +  "] (len = " + arr[ii].length + ")");
  }

  showarr ("using 2 replace + 1 split", 
           mixedfile.replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/));

and the output

  // ----- using 2 replace + 1 split
  0) [00] (len = 2)
  1) [01] (len = 2)
  2) [02] (len = 2)
  3) [03] (len = 2)
  4) [] (len = 0)
  5) [05] (len = 2)
  6) [] (len = 0)
  7) [07] (len = 2)
  8) [] (len = 0)
  9) [09] (len = 2)
Alejadro Xalabarder
  • 1,551
  • 19
  • 14
10

The first one should work:

> "a\nb".split("\n");
[ 'a', 'b' ]
> var a = "test.js\nagain.js"
undefined
> a.split("\n");
[ 'test.js', 'again.js' ]
TimWolla
  • 31,849
  • 8
  • 63
  • 96
4

I made an eol module for working with line endings in node or browsers. It has a split method like

var lines = eol.split(text)
ryanve
  • 50,076
  • 30
  • 102
  • 137