¿Cómo hacer un continuo 'wc -l' con gnu texttools?

28

Yo sé por supuesto que

cat logfile.txt | wc -l
120

me dirá el número de líneas en un archivo.

Mientras

tail -f logfile.txt

me mostrará las nuevas líneas en las que escribe otro programa logfile.txt.

¿Es posible combinar ambos para obtener un recuento continuo de líneas de actualización de logfile.txt con utilidades de texto estándar?

Yo sé sobre

watch wc -l logfile.txt

pero no quiero volver a contar todo el archivo cada vez, eso parece ser un desperdicio. Uno necesitaría un recuento de solo adjuntos cada segundo más o menos y probablemente un en \rlugar de un \nal final de la línea.

Towi
fuente
1
¿Su archivo es tan grande que contar todo es un problema? En términos de desperdicio: ¡la catproducción de tuberías wctambién es un gran desperdicio!
Bernhard
Sí, potencialmente es muy grande.
Towi

Respuestas:

36

Tal vez:

tail -n +1 -f file | awk '{printf "\r%lu", NR}'

Tenga en cuenta que generará un número para cada línea de entrada (aunque anula el valor anterior si se envía a un terminal).

O puede implementarlo a tail -fmano en shell:

n=0
while :; do 
  n=$(($n + $(wc -l)))
  printf '\r%s' "$n"
  sleep 1
done < file

(tenga en cuenta que se ejecuta hasta uno wcy un sleepcomando por segundo que no todos los shells han incorporado. Con ksh93while sleepestá incorporado, para obtener un incorporado wc(al menos en Debian), debe agregar /opt/ast/binal frente $PATH(independientemente de si ese directorio existe o no) o use command /opt/ast/bin/wc(no pregunte ...)).

Podrías usar pv, como en:

tail -n +1 -f file | pv -bl > /dev/null

Pero tenga en cuenta que agrega k, M... sufijos cuando el número es superior a 1000 (y no parece haber una forma de evitarlo ).

Stéphane Chazelas
fuente
Whow a su tail | awksolución. Conozca sus opciones: -n +0no se me habría ocurrido en esta combinación.
Towi
2
whoo! pv- Otra herramienta nueva y útil. gracias un montón.
Towi
Con grep puede agregar un filtro a su transmisión:tail -n +0 -f <my.log> | grep --line-buffered <mystring> | awk '{printf "\r%lu", NR}'
tombolinux
2
@tombolinux, awkes un superconjunto de grep. tail -n +0 -f file | awk '/mystring/ {printf "\r%lu", ++n}'
Stéphane Chazelas
Guay. añadoEND{print ""} para awkimprimir una nueva línea al final.
pLumo
6

Intenta contarlo con puro bashsin wc:

a=0 ; tail -f file | while read -r line ; do ((a++)) ; echo $a ; done

o incluso así para reescribir el valor anterior:

a=0 ; tail -f file | while read -r line ; do ((a++)) ; echo -ne "\r$a" ; done
prisa
fuente
1

No creo que haya algo así. Pero debería ser fácil preparar algo como:

#!/usr/bin/perl

$for_a_while = 1;

$oldcount = -1;
$count = 0;
open($fh, "<", $ARGV[0]);

for (;;) {
  for ($curpos = tell($fh); <$fh>; $curpos = tell($fh)) {
    $count++;
  }
  if($count != $oldcount) {
    print "$count\n";
    $oldcount = $count;
  }
  sleep($for_a_while);
  seek($fh, $curpos, 0);
}

(Idea general cunada de perlfunc(1))

vonbrand
fuente
1
El número aumentaría cada vez que hagas un printf foo >> file. Que había necesidad de contar los caracteres de nueva línea (como wc -llo hace en la solución de la envoltura sugerí), no los registros devueltos por <$fh>. No creo que necesites usar tello seeknada.
Stéphane Chazelas
La <$fh>lee una línea por defecto, no registra. La página de manual de Perl citada dice que lo haga de esta manera en aras de un entorno posiblemente no cooperativo (podría depender del sistema de archivos, supongo que NFS u otros sistemas de archivos montados en red pueden requerir un poco de insistencia).
vonbrand
Pruébelo usted mismo, al llegar al final del archivo, <$fh>devolverá un registro incluso si no está terminado por un carácter de nueva línea. Entonces, si perlestá sentado al final del archivo, y alguien más tarde hace un printf foo >> file, entonces <$fh>regresará foo(no una línea ya que no termina con un carácter de nueva línea), y $countse incrementará aunque no se haya agregado una línea adicional al archivo.
Stéphane Chazelas
¿Se suponía que OP debía monitorear los archivos de registro escritos una línea a la vez?
vonbrand
No, por eso su solución puede no funcionar. Por ejemplo, si las aplicaciones que escriben en el archivo amortiguan su salida, entonces, en cualquier momento dado, es probable que la última línea no finalice, por lo que se contará dos veces.
Stéphane Chazelas
0

Continuando con la solución basada en awk: es posible que no necesite ver el contador marcando cada línea en su registro; Si ese es el caso, puede tenerlo así (el número cambiaría por cada 10 líneas):

tail -n +0 logfile.txt | \
    awk 'a+=1{}a%10==0{printf "\r%lu", a}END{printf "\r%lu", a}'
artyom
fuente