contar líneas en un archivo

65

Estoy seguro de que hay muchas maneras de hacer esto: ¿cómo puedo contar el número de líneas en un archivo de texto?

$ <cmd> file.txt
1020 lines
Chris Smith
fuente

Respuestas:

99

La forma estándar es con wc, que toma argumentos para especificar lo que debe contar (bytes, caracteres, palabras, etc.); -les para líneas:

$ wc -l file.txt
1020 file.txt
Michael Mrozek
fuente
¿Cómo cuento las líneas en un archivo si quiero ignorar los comentarios? En concreto, quiero no contar con las líneas que comienzan con un signo +, algún espacio en blanco (puede ser sin espacio en blanco) y luego un%, que es la forma en líneas de comentarios aparecen en un git diff de un archivo de MATLAB. Intenté hacer esto con grep, pero no pude encontrar la expresión regular correcta.
Gdalya
@Gdalya espero la siguiente tubería hará esto (no hay pruebas fueron perfomed): cat matlab.git.diff | sed -e '/^\+[ ]*.*\%$/d' | wc -l. /regexp/delimina una línea si coincide regexpy -eactiva una sintaxis adecuada (IMNSHO) para regexp.
dbanet
2
¿Por qué no simplemente grep -v '^+ *%' matlab.git.diff | wc -l?
celtschk
@celtschk, siempre que esto sea habitual en las líneas de comentarios: ¿es posible modificar su grepcomando para considerar como casos de comentarios como " + Hello"(tenga en cuenta los espacios antes del +)?
Sopalajo de Arrierez
1
@SopalajodeArrierez: Por supuesto que es posible: grep -v '^ *+' matlab.git.diff | wc -l(supongo que los signos de comillas no estaban destinados a formar parte de la línea; también supongo que ambas líneas con y sin espacios en frente +están destinadas a ser comentarios; si en al menos un espacio es obligatorio, reemplace la estrella *con \+, o simplemente agregue otro espacio delante de la estrella). Probablemente, en lugar de hacer coincidir solo espacios, desearía hacer coincidir espacios en blanco arbitrarios; para esto reemplace el espacio con [[:space:]]. Tenga en cuenta que también he eliminado la coincidencia %ya que no está en su ejemplo.
celtschk
15

Como dijo Michael, wc -les el camino a seguir. Pero, en caso de que inexplicablemente tenga bash, perlo awkno wc, aquí hay algunas soluciones más:

Solo Bash

$ LINECT=0; while read -r LINE; do (( LINECT++ )); done < file.txt; echo $LINECT

Soluciones Perl

$ perl -lne 'END { print $. }' file.txt

y lo mucho menos legible:

$ perl -lne '}{ print $.' file.txt

Awk Solution

$  awk 'END {print NR}' file.txt
Steven D
fuente
15

Steven D olvidó GNU sed:

sed -n '$=' file.txt

Además, si desea el recuento sin generar el nombre de archivo y está utilizando wc:

wc -l < file.txt

Sólo por el gusto de hacerlo:

cat -n file.txt | tail -n 1 | cut -f1
Dennis Williamson
fuente
2
O grep -c '', o tr -dc '\n' | wc -c, o nl -ba -nln | tail -n 1 |sed -e 's/[^0-9].*//'... ¿Alguno de estos es útil en sí mismo (a diferencia de las cosas sobre las que construir para hacer un programa que haga más que contar líneas), aparte de wc -ly puro (ba) sh?
Gilles 'SO- deja de ser malvado'
1
@Gilles: Creo que la frase "muchas maneras" en la pregunta desencadenó un desafío al que Steve y yo nos enfrentamos.
Dennis Williamson, el
1
@Gilles:sed 's/.*//' file.txt | uniq -c
Dennis Williamson
2
@Gilles: Oh, quisiste decir primero . uniq -c -w 0 file.txty puedes cut -c -7mantener solo el número. O, más POSIXly: uniq -c file.txt | awk '{c+=$1}END{print c}'. ¿Qué tal dc(aunque no sea POSIX)? uniq -c file.txt | cut -c -7 | sed '$alax' | dc -e '[pq]sb[+z1=blax]sa' -. bces POSIX: uniq -c file.txt | cut -c -7 | sed -n ':a;${s/\n/ + /gp;b};N;ba' | bc. La respuesta fácil si se asume una longitud de línea limitada: uniq -c -f 100000 file.txt.
Dennis Williamson, el
1
@JosipRodin: Citas agregadas
Dennis Williamson
11

Palabra de advertencia al usar

wc -l

porque wc -l funciona contando \ n, si la última línea de su archivo no termina en una nueva línea, el recuento de líneas se desactivará en 1. (de ahí la convención anterior que deja nueva línea al final de su archivo)

Dado que nunca puedo estar seguro de si un archivo dado sigue la convención de terminar la última línea con una nueva línea o no, recomiendo usar cualquiera de estos comandos alternativos que incluirán la última línea en el conteo independientemente de la nueva línea o no.

sed -n $= filename
perl -lne 'END { print $. }' filename
awk 'END {print NR}' filename
grep -c '' filename
pretzels1337
fuente
buen resumen Y bienvenidos a Unix y Linux
Sebastian
Hm es la última pieza realmente línea?
gena2x
1
Estoy seguro de que depende del uso de todos; porque la 'última pieza' suele ser una línea de texto que alguien no completó con una nueva línea. El caso de uso que encuentro con mayor frecuencia es un archivo con una sola cadena de texto que no termina en una nueva línea. wc -l contaría esto como "0", cuando de otro modo esperaría un recuento de "1".
pretzels1337
3

En caso de que solo tenga bash y absolutamente ninguna herramienta externa disponible, también puede hacer lo siguiente:

count=0
while read
do
  ((count=$count+1))
done <file.txt
echo $count

Explicación: el bucle lee la entrada estándar línea por línea ( read; como de todos modos no hacemos nada con la entrada de lectura, no se proporciona ninguna variable para almacenarla), y aumenta la variable countcada vez. Debido a la redirección ( <file.txtdespués done), la entrada estándar para el bucle es de file.txt.

celtschk
fuente
2

Siempre puede usar el comando de la grepsiguiente manera:

grep -c "^" file.txt

Contará todas las filas reales de file.txt, ya sea que su última fila contenga o no un carácter LF al final.

Paolo
fuente