Cómo contar el número de líneas de una cadena en javascript

81

Quiero contar el número de líneas en una cadena

Intenté usar esta respuesta de stackoverflow:

lines = str.split("\r\n|\r|\n"); 
return  lines.length;

en esta cadena (que originalmente era un búfer):

 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

y por alguna razón obtuve líneas = '1'.

¿Alguna idea de cómo hacer que funcione?

Itzik984
fuente
3
@BookOfZeus "\ n" y "\ r" son manejados por su expresión regular. "\ n \ r" está mal.
bezmax
oh, lo veo, tienes razón mi mal
Libro de Zeus
Respondí una pregunta relacionada: "¿Cuál es la forma más rápida de probar una cantidad mínima de líneas o tokens?" stackoverflow.com/questions/39554154/…
Joe Lapp
@bezmax "\ n \ r" es necesario para el texto pegado.
Supreme Dolphin
@SupremeDolphin No, no lo es, al menos no para el ejemplo dado. Consulte en.wikipedia.org/wiki/… : "La línea de solicitud y otros campos de encabezado deben terminar con <CR> <LF>", es decir \r\n.
bezmax

Respuestas:

138

Usando una expresión regular puedes contar el número de líneas como

 str.split(/\r\n|\r|\n/).length

Alternativamente, puede probar el método dividido como se muestra a continuación.

var lines = $("#ptest").val().split("\n");  
alert(lines.length);

solución de trabajo: http://jsfiddle.net/C8CaX/

Pavana
fuente
2
Falla para este caso de prueba: 'Roomy Below:\n\nStart again.'. Detecta 3 líneas, cuando, visualmente, hay 4. Esto se debe a que la división fusiona ambas líneas nuevas.
SimplGy
4
@SimplGy ¿Qué? No falla. Detecta 3 líneas porque hay 3 líneas, incluso visualmente. console.log('Roomy Below:\n\nStart again.')te da 3 líneas. Si dividir líneas nuevas fusionadas, esto no funcionaría:, console.log('Roomy Below:\n\nStart again.'.split('\n').join('\n'))pero lo hace y obtiene las mismas 3 líneas nuevamente.
Jools
1
Tienes razón Jools, arruiné este caso de recreación porque visualmente son 3 líneas (la primera \ n termina una línea de texto y la segunda crea una línea en blanco). Estoy seguro de que mi objeción se basó en un escenario de la vida real en algún momento, pero no tengo idea de qué en este momento.
SimplGy
4
Si el texto sólo toma '\ n' para los caracteres de nueva línea (por ejemplo, un <textarea>'s value), se puede considerar el uso TEXT.match(/^/mg).length.
Константин Ван
su respuesta es incorrecta, considere el caso "\ n \ n". Solo hay dos líneas. Pero su código da como resultado 3. Lo cual no es correcto.
Khamidulla
42

Otra solución breve y potencialmente más eficaz que la división es:

const lines = (str.match(/\n/g) || '').length + 1
ngryman
fuente
esta es una solución mucho mejor
asmmahmud
3
como esta solución, pequeña mejora: en \r?realidad no está haciendo nada, (str.match(/\n/g) || '').lengthproduce el mismo resultado, ¿no?
Samuel Kirschner
Mejor solución, ya que la función de división crea una nueva matriz que es más pesada que esta solución.
hashed_name
ambos métodos crean una nueva matriz ... str.match devuelve una matriz y la división también ... El método de división devuelve una matriz de cadenas, pero str.match devuelve una matriz de objetos. Creo que un objeto ocupa más espacio en la memoria que una cadena ...
Bruno Desprez
claro ganador en el benchmark
Mila Nautikus
9

Para dividir usando una expresión regular, use /.../

lines = str.split(/\r\n|\r|\n/); 
David Hedlund
fuente
9

Hmm sí ... lo que estás haciendo está absolutamente mal. Cuando lo digas str.split("\r\n|\r|\n"), intentará encontrar la cadena exacta "\r\n|\r|\n". Ahí es donde te equivocas. No hay tal ocurrencia en toda la cadena. Lo que realmente quieres es lo que sugirió David Hedlund:

lines = str.split(/\r\n|\r|\n/);
return lines.length;

La razón es que el método de división no convierte cadenas en expresiones regulares en JavaScript. Si desea usar una expresión regular, use una expresión regular.

Aadit M Shah
fuente
7

Hice una prueba de rendimiento comparando split con regex, con una cadena y haciéndolo con un bucle for.

Parece que el bucle for es el más rápido.

NOTA: este código 'tal cual' no es útil para windows ni macos endline, pero debería estar bien para comparar el rendimiento.

Dividir con cuerda:

split('\n').length;

Dividir con expresiones regulares:

split(/\n/).length;

Dividir usando para:

var length = 0;
for(var i = 0; i < sixteen.length; ++i)
  if(sixteen[i] == s)
    length++;

http://jsperf.com/counting-newlines/2

jperelli
fuente
gracioso, mi punto de referencia dice que el bucle for es más lento
Mila Nautikus
3

Hay tres opciones:

Usando jQuery (descargar desde el sitio web de jQuery ) - jquery.com

var lines = $("#ptest").val().split("\n");
return lines.length;

Usando Regex

var lines = str.split(/\r\n|\r|\n/);
return lines.length;

O una recreación de un bucle para cada

var length = 0;
for(var i = 0; i < str.length; ++i){
    if(str[i] == '\n') {
        length++;
    }
}
return length;
Joe
fuente
1

Aquí está el violín de muestra de trabajo

Simplemente elimine \ r \ ny "|" adicionales de tu reg ex.

Sandeep GB
fuente
0

Mejor solución, ya que la función str.split ("\ n") crea una nueva matriz de cadenas dividida por "\ n", que es más pesada que str.match (/ \ n \ g). str.match (/ \ n \ g) crea una matriz de elementos coincidentes solamente. Que es "\ n" en nuestro caso.

var totalLines = (str.match(/\n/g) || '').length + 1;
hashed_name
fuente
0
 <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>

eso funciona en mi caso

Krishna Kumar Jangid
fuente