Wie mache ich ein kontinuierliches 'wc -l' mit gnu texttools?


28

Das weiß ich natürlich

cat logfile.txt | wc -l
120

wird mir die Anzahl der Zeilen in einer Datei sagen.

Wohingegen

tail -f logfile.txt

zeigt mir die neuen Zeilen, in die ein anderes Programm schreibt logfile.txt.

Ist es möglich, beide zu kombinieren, so dass ich eine fortlaufende Aktualisierung der Zeilenanzahl von logfile.txt mit Standardtextdienstprogrammen erhalte?

Ich weiß ungefähr

watch wc -l logfile.txt

aber ich möchte nicht jedes Mal die ganze Datei neu zählen, das scheint eine Verschwendung zu sein. Man würde ungefähr jede Sekunde eine Nur-Anhänge-Zählung benötigen und wahrscheinlich eine \ranstelle einer \nam Ende der Zeile.


1
Ist Ihre Datei so groß, dass es ein Problem ist, alles neu zu erzählen? In Bezug auf Abfall: Rohrleitungen, zu denen catausgegeben wird, wcsind ebenfalls eine große Verschwendung !!
Bernhard

Ja, es ist möglicherweise sehr groß.
Bis zum

Antworten:


36

Vielleicht:

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

Beachten Sie, dass für jede Eingabezeile eine Zahl ausgegeben wird (der vorherige Wert wird jedoch überschrieben, wenn er an ein Terminal gesendet wird).

Oder Sie können das tail -fvon Hand in Shell umsetzen :

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

(Beachten Sie, dass es bis zu ein wcund zwei sleepBefehle pro Sekunde ausführt, die nicht alle Shells eingebaut haben. Wenn ksh93while sleepeingebaut ist, müssen Sie, um ein eingebautes wc(zumindest unter Debian) zu erhalten, /opt/ast/binvorne hinzufügen $PATH(unabhängig davon, ob das Verzeichnis existiert oder nicht) oder verwenden command /opt/ast/bin/wc(nicht fragen ...)).

Sie könnten verwenden pv, wie in:

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

Aber hüte dich davor, dass es ... Suffixe hinzufügt k, Mwenn die Zahl über 1000 liegt (und es scheint keinen Ausweg zu geben ).


Wie lautet Ihre tail | awkLösung ? Kennen Sie Ihre Möglichkeiten: -n +0wäre mir in dieser Kombination nicht eingefallen.
Bis zum

2
whoo! pv- Ein weiteres nützliches neues Tool. Vielen Dank.
Am

Mit grep können Sie Ihrem Stream einen Filter hinzufügen:tail -n +0 -f <my.log> | grep --line-buffered <mystring> | awk '{printf "\r%lu", NR}'
tombolinux

2
@tombolinux, awkist eine Obermenge von grep. tail -n +0 -f file | awk '/mystring/ {printf "\r%lu", ++n}'
Stéphane Chazelas

Cool. Ich füge hinzu END{print ""}, um awkam Ende eine neue Zeile zu drucken.
pLumo

6

Versuchen Sie es mit rein bashohne zu zählen wc:

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

oder sogar so, um den vorherigen Wert umzuschreiben:

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

1

Ich glaube nicht, dass es so etwas gibt. Aber es sollte einfach sein, etwas in der Art von:

#!/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);
}

(Allgemeine Idee abgeschnitten von perlfunc(1))


1
Die Zahl würde sich jedes Mal erhöhen, wenn Sie a tun printf foo >> file. Sie müssten die Zeilenumbruchzeichen zählen (wie wc -lin der von mir vorgeschlagenen Shell-Lösung), nicht die Datensätze, die von zurückgegeben wurden <$fh>. Ich denke nicht, dass Sie verwenden müssen telloder seeküberhaupt.
Stéphane Chazelas

Der <$fh>liest standardmäßig eine Zeile, keine Datensätze. Die angeführte Perl-Manpage fordert dazu auf, dies aus Gründen einer möglicherweise nicht kooperativen Umgebung zu tun (hängt möglicherweise vom Dateisystem ab, ich denke, NFS oder andere im Netzwerk installierte Dateisysteme erfordern ein bisschen Nacharbeit).
Vonbrand

Probieren Sie es aus, <$fh>sobald das Dateiende erreicht ist, wird ein Datensatz zurückgegeben, auch wenn er nicht durch ein Zeilenumbruchzeichen abgeschlossen wird. Also , wenn perlam Ende der Datei sitzt und jemand später kommt ein printf foo >> file, dann <$fh>wird wieder foo(keine Linie , da sie von einem Newline - Zeichen nicht beendet ist), und $countwird sogar erhöht werden , obwohl keine zusätzliche Zeile in die Datei hinzugefügt wurde.
Stéphane Chazelas

OP sollte Protokolldateien überwachen, die zeilenweise geschrieben wurden?
Vonbrand

Nein, aus diesem Grund funktioniert Ihre Lösung möglicherweise nicht. Wenn beispielsweise die Anwendungen, die in die Datei schreiben, ihre Ausgabe puffern, wird die letzte Zeile wahrscheinlich zu einem bestimmten Zeitpunkt nicht beendet, sodass sie zweimal gezählt wird.
Stéphane Chazelas

0

Fortsetzung der awk-basierten Lösung: Möglicherweise müssen Sie den Zähler nicht für jede Zeile in Ihrem Protokoll ankreuzen. Wenn dies der Fall ist, können Sie es so haben (die Zahl würde sich für jeweils 10 Zeilen ändern):

tail -n +0 logfile.txt | \
    awk 'a+=1{}a%10==0{printf "\r%lu", a}END{printf "\r%lu", a}'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.