bash echo número de líneas de archivo dadas en una variable bash sin el nombre del archivo

79

Tengo las siguientes tres construcciones en un script bash:

NUMOFLINES=$(wc -l $JAVA_TAGS_FILE)
echo $NUMOFLINES" lines"

echo $(wc -l $JAVA_TAGS_FILE)" lines"

echo "$(wc -l $JAVA_TAGS_FILE) lines"

Y ambos producen una salida idéntica cuando se ejecuta el script:

121711 /home/slash/.java_base.tag lines
121711 /home/slash/.java_base.tag lines
121711 /home/slash/.java_base.tag lines

Es decir, el nombre del archivo también se repite (lo cual no quiero). ¿Por qué fallan estos scriplets y cómo debo generar una limpieza?

121711 lines

?

Marco Junio ​​Bruto
fuente
Posible duplicado de obtener solo el entero de wc en bash
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

157

Un ejemplo usando sus propios datos

Puede evitar tener su nombre de archivo incrustado en la variable NUMOFLINES usando la redirección desde JAVA_TAGS_FILE , en lugar de pasar el nombre de archivo como un argumento a wc . Por ejemplo:

NUMOFLINES=$(wc -l < "$JAVA_TAGS_FILE")

Explicación: Utilice canalizaciones o redireccionamiento para evitar nombres de archivo en la salida

La utilidad wc no imprimirá el nombre del archivo en su salida si la entrada se toma de una tubería o un operador de redirección. Considere estos varios ejemplos:

# wc shows filename when the file is an argument
$ wc -l /etc/passwd
41 /etc/passwd

# filename is ignored when piped in on standard input
$ cat /etc/passwd | wc -l
41

# unusual redirection, but wc still ignores the filename
$ < /etc/passwd wc -l
41

# typical redirection, taking standard input from a file
$ wc -l < /etc/passwd
41

Como puede ver, la única vez que wc imprimirá el nombre del archivo es cuando se pasa como un argumento, en lugar de como datos en la entrada estándar. En algunos casos, es posible que desee que se imprima el nombre del archivo, por lo que es útil saber cuándo se mostrará.

Todd A. Jacobs
fuente
1
tenga en cuenta que este enfoque no incluirá la última línea si la última línea no termina con el carácter de fin de línea. Vea mi solución a continuación.
ling
15

wc no puede obtener el nombre del archivo si no le da uno.

wc -l < "$JAVA_TAGS_FILE"
Ignacio Vázquez-Abrams
fuente
2
Bueno, entonces no lo hagas. Simplemente pase el archivo a wc's stdin como se muestra en la respuesta. Así que cat "$JAVA_TAGS_FILE" | wc -lo, equivalentemente, wc -l < "$JAVA_TAGS_FILE". De esta manera, wcsolo obtiene datos sin procesar, no el nombre del archivo.
Witiko
12

También puedes usar awk:

awk 'END {print NR,"lines"}' filename

O

awk 'END {print NR}' filename

Javier López
fuente
5

(aplicar en Mac y probablemente en otros Unix)

En realidad, existe un problema con el enfoque wc: no cuenta la última línea si no termina con el símbolo de fin de línea.

Usa esto en su lugar

nbLines=$(cat -n file.txt | tail -n 1 | cut -f1 | xargs)

o incluso mejor (gracias gniourf_gniourf):

nblines=$(grep -c '' file.txt)

Nota: El enfoque awk de chilicuil también funciona.

abadejo
fuente
2
¡Método muy complicado! Tal vez desee en su nblines=$(grep -c '' file)lugar (que es la forma canónica de contar líneas incompletas en este caso). Sin embargo, tenga en cuenta que, según POSIX, está contando las líneas incompletas (y no las líneas ). De hecho, se trata de un archivo binario y no de un archivo de texto .
gniourf_gniourf
@gniourf_gniourf Gracias, no sabía nada de eso, funciona muy bien y es aún más conciso.
ling
quizás sea una mejor soluciónnblines=$(($(cat "file.txt" | wc -l) + 1))
Andrey Izman
3

Es muy simple:

NUMOFLINES=$(cat $JAVA_TAGS_FILE | wc -l )

o

NUMOFLINES=$(wc -l $JAVA_TAGS_FILE | awk '{print $1}')
Slava Semushin
fuente
El primero es el uso inútil del gato.
kap
@kap No, solo se ve así. Si se deshace de él cat, tendría el segundo ejemplo porque wc -ldevuelve 2 columnas cuando se usa solo con un archivo.
Slava Semushin
-3

Normalmente uso la función 'retroceso' de bash

export NUM_LINES=`wc -l filename`

Tenga en cuenta que la 'marca' es la 'marca inversa', por ejemplo, 'no la comilla simple normal

Russ Hore
fuente
5
Esa es solo una notación diferente y no resuelve el problema de que el nombre del archivo sea parte del resultado.
Izzy