281

I have a string with new line characters. I want to convert that string into an array, and for every new line, jump one index place in the array.

If the string is:

My text1
My text2
My text3

The result I want is this:

Array
(
    [0] => My text1
    [1] => My text2
    [2] => My text3
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Johan
  • 18,814
  • 30
  • 70
  • 88
  • You should normalize the newlines first, probably. The method `s($yourString)->normalizeLineEndings()` is available with https://github.com/delight-im/PHP-Str (library under MIT License) which has lots of other useful string helpers. You may want to take a look at the source code. – caw Jul 25 '16 at 03:23

19 Answers19

440

I've always used this with great success:

$array = preg_split("/\r\n|\n|\r/", $string);

(updated with the final \r, thanks @LobsterMan)

Wouter J
  • 41,455
  • 15
  • 107
  • 112
David
  • 5,349
  • 1
  • 21
  • 15
  • 1
    This is the answer. The validated one is WRONG. Well, hesselbom has it too... You could also use this equivalent: preg_split('/\n|\r/', $string, -1, PREG_SPLIT_NO_EMPTY); for the sake of beauty :) Why is this the only good answer? Because you cannot assume what type of end of line you will get: Mac (\r), Windows (\r\n), or Unix (\n). – Ninj Jan 08 '15 at 23:08
  • 17
    `\R` [matches](http://php.net/manual/en/regexp.reference.escape.php) `\n`, `\r` and `\r\n` – mpen Oct 13 '16 at 17:44
  • 2
    Or shorter `/\r?\n/` – Jason Schilling Oct 23 '19 at 16:59
  • 1
    This example is correct because you can't just take any split operation that is just based on a single character. If you would do that, triggering on '\r' or '\n' you will end up with a superfluous empty line in case of a Windows "\r\n" ending. And it's important that the two-character Windows separator is tested first. – AndresRohrAtlasInformatik Feb 14 '20 at 10:56
335

You can use the explode function, using "\n" as separator:

$your_array = explode("\n", $your_string_from_db);

For instance, if you have this piece of code:

$str = "My text1\nMy text2\nMy text3";
$arr = explode("\n", $str);
var_dump($arr);

You'd get this output:

array
  0 => string 'My text1' (length=8)
  1 => string 'My text2' (length=8)
  2 => string 'My text3' (length=8)


Note that you have to use a double-quoted string, so \n is actually interpreted as a line-break.
(See that manual page for more details.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • Although it's simple, you explained it perfectly. – Daniel Sorichetti Sep 27 '09 at 14:50
  • 61
    Instead of `\n` you can use the predefined constant `PHP_EOL`. – Tim Jul 19 '12 at 14:58
  • 47
    Everyone please be careful with this solution, as it does not work on all newlines. I've had the most success with David's answer – Maurice Aug 29 '12 at 07:31
  • 2
    You must split at either \n or\r to be able to handle all kind of texts - this will only work with linux & windows newlines. Mac newlines will be disregarded! (\r) – Steve Horvath Jun 02 '16 at 01:30
  • 1
    I guess Tims answer/comment is not right, because this will only match the linebreak an YOUR system, but when you get strings that has linebreaks from other systems it wont work! Had this problem with emails – Asara Nov 30 '16 at 12:20
  • It's better split by `\r\n` for example: `$your_array = explode("\r\n", $your_string_from_db);` – Luis Lorenzo Mar 29 '17 at 14:11
  • 10
    Nope this answer and the comments on this answer are WRONG! Because this does not factor in the OS newline character, especially not `PHP_EOL`. You must use `preg_split("/\\r\\n|\\r|\\n/", $value)`. – kjdion84 Sep 18 '17 at 15:24
  • If you had an multi line string (for example from an textarea) explode using \n does not work but PHP_EOL did work properly. – Adeel Raza Azeemi Sep 02 '21 at 06:47
293

A line break is defined differently on different platforms, \r\n, \r or \n.

Using RegExp to split the string you can match all three with \R

So for your problem:

$array = preg_split ('/$\R?^/m', $string);

That would match line breaks on Windows, Mac and Linux!

hesselbom
  • 3,520
  • 3
  • 16
  • 16
  • 3
    I used this as well instead of the accepted answer and any other answers on this thread. Just leaving this comment as an informative. – Seth Malaki Jun 01 '12 at 12:55
  • 3
    Actually, this did not work for me. Sometimes newlines where still present in the array keys. – Maurice Aug 29 '12 at 07:29
  • 2
    Related: [How to replace different newline styles in PHP the smartest way?](http://stackoverflow.com/q/7836632/367456) – hakre Dec 23 '12 at 14:24
  • 37
    Just use `$array = preg_split ('/\R/', $string);` – Jan Goyvaerts Feb 15 '13 at 03:42
  • 19
    Not working sometimes! `preg_split("/\r\n|\n|\r/", $string)` better choice – Alexey B. Aug 28 '13 at 10:26
  • 2
    I second what 'Maurice' said, not working for me. The solution given by 'Jan' worked, though... – pedromanoel Oct 24 '13 at 15:27
  • 1
    Try this with `$string="1\n2\n"` and you will see that the answer by @hesselbom keeps the newline in the second array element, whereas @JanGoyvaerts 's answer correctly adds an empty third element. This is because @hesselbom requires a start of a new line after the linebreak, which is not there if the string ends with `\n`. Try it here: http://sandbox.onlinephpfunctions.com/code/bb93ce231c45e141e4d777d046123a225ea9af49 – Christopher K. Sep 08 '17 at 13:05
  • `Warning: Unexpected character in input: '\' (ASCII=92) state=1 on line 9` `Parse error: syntax error, unexpected T_STRING, expecting T_VARIABLE or '$' on line 9` That's the like with the regex. – Rolf Nov 06 '17 at 14:48
  • May want to use (preg_split(....... , -1, PREG_SPLIT_NO_EMPTY) to avoid empty arrays getting into your result, your file may have extra newlines at the end....) – Mark Watkins Jun 22 '18 at 13:54
  • This method will leave behind \n characters, which is probably not desirable. – Keith Turkowski Aug 28 '20 at 05:21
  • I recommend `$array = preg_split ('/\R/u', $string);` because `u` modifier is required if string may contain UTF-8 characters. Try string '腰' with and without modifier to see the difference. Everything else not needed. – kdmitry Jul 23 '21 at 12:24
39

PHP already knows the current system's newline character(s). Just use the EOL constant.

explode(PHP_EOL,$string)
voidstate
  • 7,937
  • 4
  • 40
  • 52
  • 21
    Yes, but one can edit a file or as in this example a db entry in Windows then use it on a Linux system, for example. I think a general approach would suit better. – Cranio Dec 07 '12 at 11:03
  • 2
    I'm not sure this is right. If a text area on a web page gets submitted, it could have different end-of-line characters depending on the user's browser, not the server's operating system. So no matter what OS you are using, you will need to be able to parse anything. This is assuming you're doing web stuff of course. – Magmatic Nov 08 '16 at 20:52
  • 1
    You might then have to use `trim()` on the resulting strings to remove any extraneous whitespace. – Tim Dec 07 '16 at 15:12
38

An alternative to Davids answer which is faster (way faster) is to use str_replace and explode.

$arrayOfLines = explode("\n",
                    str_replace(["\r\n","\n\r","\r"],"\n",$str)
            );

What's happening is:
Since line breaks can come in different forms, I str_replace \r\n, \n\r, and \r with \n instead (and original \n are preserved).
Then explode on \n and you have all the lines in an array.

I did a benchmark on the src of this page and split the lines 1000 times in a for loop and:
preg_replace took an avg of 11 seconds
str_replace & explode took an avg of about 1 second

More detail and bencmark info on my forum

Reed
  • 14,703
  • 8
  • 66
  • 110
  • Your forum link (and the entire domain) seem to be down – Nikita 웃 Jul 29 '18 at 07:58
  • `\n\r` ...Which operating system uses the newline sequence in reverse like this? – mickmackusa Dec 20 '20 at 20:51
  • @mickmackusa, none that I know of. It was so long ago, I'm not sure why I did it that way. Thinking I should remove the `\n\r`? – Reed Dec 20 '20 at 21:24
  • 1
    As far as I know, you only need to retain `\r\n` in the search array (and for that matter, it doesn't need to be an array anymore). I am interested in the claim that `preg_` was 11 times slower. You did not include the pattern that you used. Your above snippet makes 4 passes over the input. A good `preg_` technique will make only one pass over the input. Regex is not known for its speed, but I think your claim requires substantiation. Please post your benchmark details if you are going to keep this performance claim in your answer. – mickmackusa Dec 20 '20 at 22:05
22

David has a great direction, but it missed \r. This worked for me:

$array = preg_split("/(\r\n|\n|\r)/", $string);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
LobsterMan
  • 1,158
  • 1
  • 11
  • 18
16

You don't need preg_* functions, preg patterns, str_replace within, etc. in order to successfully break a string into array by newlines. In all scenarios, be it Linux, Mac, or Windows, this will do.

<?php
    $array = explode(PHP_EOL, $string);
    // ...
    $string = implode(PHP_EOL, $array);
?>

PHP_EOL is a constant holding the line break character(s) used by the server platform.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Spooky
  • 1,235
  • 15
  • 17
  • 7
    the file could come from another system with different new lines, particularry in a net environment for wich is used PHP – Luca C. Jul 25 '16 at 08:54
  • Which is exactly the reason this constant exists.. and handles that particular problem. – Spooky Jul 28 '16 at 15:14
  • if you take a file from windows it does not match the same as a file from unix, or mac, right? – Luca C. Jul 28 '16 at 15:53
  • If You are using pure utf-8 all the time, everywhere, utf8 files included, normally, and You have nothing else but PHP_EOL inside code of Yours for line break detections, it will be matched as described, and no unpredicted behavior will occur. Keep in mind that it's not only me yelling and claiming this. PHP_EOL usability is quite confirmed. – Spooky Jul 28 '16 at 16:04
  • in my case, tha case for which I read this question, could not always work. I download files from other sites and split them by lines, thay ca be UTF8 or not, they can be from windows or unix new line, so I used a regexp matching any new line variant – Luca C. Jul 29 '16 at 07:44
  • 1
    In Your case, if sources come from somewhere else and aren't formed well, whatever, it's maybe better if You use str_replace (faster than regexp). ... all in all, be it regexp. or str_replace or PHP_EOL, there's one good old sentence saying: "If it works - don't touch it!". :) – Spooky Jul 29 '16 at 08:18
15

Use: $array = preg_split('/\s*\R\s*/', trim($text), NULL, PREG_SPLIT_NO_EMPTY);

This worked best for me because it also eliminates leading (second \s*) and trailing (first \s*) whitespace automatically and also skips blank lines (the PREG_SPLIT_NO_EMPTY flag).

Options

If you want to keep leading whitespace, simply get rid of the second \s* and make it an rtrim() instead...

$array = preg_split('/\s*\R/', rtrim($text), NULL, PREG_SPLIT_NO_EMPTY);

If you need to keep empty lines, get rid of the NULL (it is only a placeholder) and PREG_SPLIT_NO_EMPTY flag, like so...

$array = preg_split('/\s*\R\s*/', trim($text));

Or keeping both leading whitespace and empty lines...

$array = preg_split('/\s*\R/', rtrim($text));

I don't see any reason why you'd ever want to keep trailing whitespace, so I suggest leaving the first \s* in there. But, if all you want is to split by new line (as the title suggests), it is this simple (as mentioned by Jan Goyvaerts)...

$array = preg_split('/\R/', $text);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Deen Foxx
  • 181
  • 1
  • 4
11

There is quite a mix of direct and indirect answers on this page and some good advice in comments, but there isn't an answer that represents what I would write in my own project.

PHP Escape Sequence \R documentation: https://www.php.net/manual/en/regexp.reference.escape.php#:~:text=line%20break,\r\n

Code: (Demo)

$string = '
My text1

My text2


My text3


';

var_export(
    preg_split('/\R+/', $string, 0, PREG_SPLIT_NO_EMPTY)
);

Output:

array (
  0 => 'My text1',
  1 => 'My text2',
  2 => 'My text3',
)

The OP makes no mention of trimming horizontal whitespace characters from the lines, so there is no expectation of removing \s or \h while exploding on variable (system agnostic) new lines.

While PHP_EOL is sensible advice, it lacks the flexibility appropriately explode the string when the newline sequence is coming from another operating system.

Using a non-regex explode will tend to be less direct because it will require string preparations. Furthermore, there may be mopping up after the the explosions if there are unwanted blank lines to remove.

Using \R+ (one or more consecutive newline sequences) and the PREG_SPLIT_NO_EMPTY function flag will deliver a gap-less, indexed array in a single, concise function call. Some people have a bias against regular expressions, but this is a perfect case for why regex should be used. If performance is a concern for valid reasons (e.g. you are processing hundreds of thousands of points of data), then go ahead and invest in benchmarking and micro-optimization. Beyond that, just use this one-line of code so that your code is brief, robust, and direct.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
9
explode("\n", $str);

The " (instead of ') is quite important as otherwise, the line break wouln't get interpreted.

Damien MATHIEU
  • 31,924
  • 13
  • 86
  • 94
7
<anti-answer>

As other answers have specified, be sure to use explode rather than split because as of PHP 5.3.0 split is deprecated. i.e. the following is NOT the way you want to do it:

$your_array = split(chr(10), $your_string);

LF = "\n" = chr(10), CR = "\r" = chr(13)

</anti-answer>
Tom
  • 14,041
  • 16
  • 64
  • 80
4

Use:

$str = "My text1\nMy text2\nMy text3";
$arr = explode("\n", $str);

foreach ($arr as $line_num => $line) {
    echo "Line #<b>{$line_num}</b>: " . htmlspecialchars($line) . "<br />\n";
}

True array:

$str = "My text1\nMy text2\nMy text3";
$arr = explode("\n", $str);

$array = array();

foreach ($arr as $line) { // loop line by line and convert into array
    $array[] = $line;
};

print_r($array); // display all value

echo $array[1]; // display index 1

Embed online:

body, html, iframe {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
<iframe src="https://ideone.com/vE1gst" ></iframe>
antelove
  • 3,216
  • 26
  • 20
3

You can use this:

 str_getcsv($str, PHP_EOL);
parisssss
  • 803
  • 16
  • 36
3

That's my way:

$lines = preg_split('/[\r\n]+/', $db_text, NULL, PREG_SPLIT_NO_EMPTY);

This also will skip all empty lines too.

Axel
  • 31
  • 2
3

For anyone trying to display cronjobs in a crontab and getting frustrated on how to separate each line, use explode:

$output = shell_exec('crontab -l');
$cron_array = explode(chr(10),$output);

using '\n' doesnt seem to work but chr(10) works nicely :D

hope this saves some one some headaches.

Jeff
  • 31
  • 1
  • Hi Jeff, welcome to SO. You should rewrite this as a question and answer, rather than an answer on somebody else's question. This is a Q&A site, not a general forum. Have a look at the FAQ - http://stackoverflow.com/faq – Rebecca Scott Jul 13 '11 at 07:35
  • Using `'\n'` doesn't work because escape sequences are not interpreted in single quotes, you need to use double quotes instead: `"\n"` instead of `'n'` Read http://php.net/manual/en/language.types.string.php – Christopher K. Sep 08 '17 at 12:50
2

You can do a $string = nl2br($string) so that your line break is changed to

<br />. 

This way it does not matter if the system uses \r\n or \n or \r

Then you can feed it into an array:

$array = explode("<br />", $string);
  • 1
    Note: [nl2br](http://php.net/manual/en/function.nl2br.php) does not replace the line breaks... it only inserts a break tag before each line break. So all of your array items other than the first will begin with a line break. If that doesn't matter to you, then this method is the fastest. If that does matter, [Jakar's answer](http://stackoverflow.com/a/28725803/1408717) is the fastest. – Aust Oct 20 '15 at 20:56
  • The performance benefit of a non-regex technique may be true, but Reed's benchmark details are not currently included. There may be untruths in the details/results. – mickmackusa Dec 20 '20 at 22:10
2

I picked this up in the PHP documentation:

<?php
  // Split the phrase by any number of commas or space characters,
  // which include " ", \r, \t, \n and \f

  $keywords = preg_split("/[\s,]+/", "hypertext language, programming");
  print_r($keywords);
?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
korwalskiy
  • 927
  • 12
  • 12
  • The answer would definitely mangle the OP's text. This is the correct answer to a different question; in other words, this is provably incorrect for this page. – mickmackusa Dec 20 '20 at 21:59
0

Using only the 'base' package is also a solution for simple cases:

> s <- "a\nb\rc\r\nd"
> l <- strsplit(s,"\r\n|\n|\r")
> l  # the whole list...
[[1]]
[1] "a" "b" "c" "d"
> l[[1]][1] # ... or individual elements
[1] "a"
> l[[1]][2]
[1] "b"
> fun <- function(x) c('Line content:', x) # handle as you wish
> lapply(unlist(l), fun)
Roque
  • 359
  • 4
  • 8
-1

This method always works for me:

$uniquepattern = "gd$#%@&~#" // Any set of characters which you don’t expect to be present in user input $_POST['text']. Better use at least 32 characters.
$textarray = explode($uniquepattern, str_replace("\r", "", str_replace("\n", $uniquepattern, $_POST['text'])));
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 2
    Love the swearing as part of the code. :) Anyway, replacing with \n is simpler as well as safer (look at the other answers). – Stefan Reich Mar 11 '15 at 12:50