Reputation: 16764
I would like to count the number of lines in a string. I tried to use this stackoverflow answer,
lines = str.split("\r\n|\r|\n");
return lines.length;
on this string (which was originally a buffer):
GET / HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.2 (KHTML,like Gecko) Chrome/15.0.874.121 Safari/535.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
and, for some reason, I got lines='1'
.
Any idea how to make it work?
Upvotes: 123
Views: 170568
Reputation: 2692
I've combined a few of the other answers into a performance test at https://jsperf.app/lenavi/4:
.match(/\n/g)
from @ngryman and @hashed_name:
(text.match(/\n/g) || '').length + 1
.reduce(...)
from @gil.fernandes:
[...text].reduce((a, c) => a + (c === '\n'), 1)
.split(/\r\n|\r|\n/)
from @Joe, @Pavan, @Aadit M Shah, and @David Hedlund:
text.split(/\r\n|\r|\n/).length
.split(/\n/)
for when you know the line ending, by @jperelli:
text.split(/\n/).length
.split('\n')
which is the same as above, but using a string instead of a regex, by @Krishna Jangid, @jperelli, @Joe, and @Pavan:
text.split('\n').length
Here are the results on my machine with Chrome 123.0.6312.105:
.split('\n')
is the fastest by far..split(/\n/)
and .match(/\n/g)
are virtually tied for second at 59% slower..split(/\r\n|\r|\n/)
is about 87% slower..reduce(...)
is 99% slower. Not even in the same ballpark.The results are different (on my machine) with Firefox 123.0.1:
.split(/\n/)
and .match(/\n/g)
are virtually tied for first. I'm a little surprised that .split()
did this well. Perhaps the SpiderMonkey JavaScript engine is special-casing this particular call..split('\n')
is ~50% slower. I'm very surprised by the difference here between using a one-character string and a one-character regex..split(/\r\n|\r|\n/)
is about 66% slower, or 1/3 the speed, which makes sense because it is doing up to 3x the comparisons..reduce(...)
is 99% slower (again).Node uses the same JavaScript engine (V8) as Chrome.
Upvotes: 0
Reputation: 7672
Another short, potentially more performant than split, solution is:
const lines = (str.match(/\n/g) || '').length + 1
to avoid possible errors, it can help to convert it explicitly into a string ( https://stackoverflow.com/a/5196710/2891692 ) :
const lines = (String(str).match(/\n/g) || '').length + 1
Upvotes: 83
Reputation: 14601
Another solution for this problem using the spread operator and no regular expressions would be:
const lines = [...csv].reduce((a, c) => a + (c === '\n' ? 1 : 0), 0)
const csv = `
demo_budget_2021_v4_wk_9,test,Civil,Spares,test,false,12,2021,100
demo_budget_2021_v4_wk_9,test,Civil,Spares,test,false,11,2021,100
demo_budget_2021_v4_wk_9,test,Civil,Spares,test,false,10,2021,100
demo_budget_2021_v4_wk_9,test,Civil,Spares,test,false,9,2021,100
`
const lines = [...csv].reduce((a, c) => a + (c === '\n' ? 1 : 0), 0)
console.log(lines);
Upvotes: 2
Reputation: 397
I was testing out the speed of the functions, and I found consistently that this solution that I had written was much faster than match
ing. We check the new length of the string as compared to the previous length.
const lines = str.length - str.replace(/\n/g, "").length+1;
let str = `Line1
Line2
Line3`;
console.time("LinesTimer")
console.log("Lines: ",str.length - str.replace(/\n/g, "").length+1);
console.timeEnd("LinesTimer")
Upvotes: 1
Reputation: 5410
<script type="text/javascript">
var multilinestr = `
line 1
line 2
line 3
line 4
line 5
line 6`;
totallines = multilinestr.split("\n");
lines = str.split("\n");
console.log(lines.length);
</script>
thats works in my case
Upvotes: 1
Reputation: 551
Better solution, as str.split("\n") function creates new array of strings split by "\n" which is heavier than str.match(/\n\g). str.match(/\n\g) creates array of matching elements only. Which is "\n" in our case.
var totalLines = (str.match(/\n/g) || '').length + 1;
Upvotes: 2
Reputation: 7197
I made a performance test comparing split with regex, with a string and doing it with a for loop.
It seems that the for loop is the fastest.
NOTE: this code 'as is' is not useful for windows nor macos endline, but should be ok to compare performance.
Split with string:
split('\n').length;
Split with regex:
split(/\n/).length;
Split using for:
var length = 0;
for(var i = 0; i < sixteen.length; ++i)
if(sixteen[i] == s)
length++;
http://jsperf.com/counting-newlines/2
Upvotes: 8
Reputation: 538
There are three options:
Using jQuery (download from jQuery website) - jquery.com
var lines = $("#ptest").val().split("\n");
return lines.length;
Using Regex
var lines = str.split(/\r\n|\r|\n/);
return lines.length;
Or, a recreation of a for each loop
var length = 0;
for(var i = 0; i < str.length; ++i){
if(str[i] == '\n') {
length++;
}
}
return length;
Upvotes: 3
Reputation: 4329
Using a regular expression you can count the number of lines as
str.split(/\r\n|\r|\n/).length
Alternately you can try split method as below.
var lines = $("#ptest").val().split("\n");
alert(lines.length);
working solution: http://jsfiddle.net/C8CaX/
Upvotes: 196
Reputation: 74204
Hmm yeah... what you're doing is absolutely wrong. When you say str.split("\r\n|\r|\n")
it will try to find the exact string "\r\n|\r|\n"
. That's where you're wrong. There's no such occurance in the whole string. What you really want is what David Hedlund suggested:
lines = str.split(/\r\n|\r|\n/);
return lines.length;
The reason is that the split method doesn't convert strings into regular expressions in JavaScript. If you want to use a regexp, use a regexp.
Upvotes: 11
Reputation: 129792
To split using a regex use /.../
lines = str.split(/\r\n|\r|\n/);
Upvotes: 11
Reputation: 4015
Here is the working sample fiddle
Just remove additional \r\n and "|" from your reg ex.
Upvotes: 1