Bagaimana cara melakukan 'wc -l' secara kontinyu dengan texttools gnu?

28

Tentu saja saya tahu itu

cat logfile.txt | wc -l
120

akan memberi tahu saya jumlah baris dalam file.

Sedangkan

tail -f logfile.txt

akan menunjukkan kepada saya baris baru yang ditulis oleh program lain logfile.txt.

Apakah mungkin untuk menggabungkan keduanya sehingga saya mendapatkan jumlah baris yang diperbarui terus-menerus dari logfile.txt dengan utilitas teks standar?

Saya tahu tentang

watch wc -l logfile.txt

tapi saya tidak ingin menghitung ulang seluruh file setiap kali, yang sepertinya sia-sia. Orang akan membutuhkan hitungan hanya ditambahkan setiap detik atau lebih dan mungkin \rbukan sebagai \npada akhir baris.

towi
sumber
1
Apakah file Anda sebesar itu yang menceritakan semuanya adalah masalah? Dalam hal pemborosan: catkeluaran perpipaan ke wcjuga merupakan pemborosan besar !!
Bernhard
Ya, ini berpotensi sangat besar.
towi

Jawaban:

36

Mungkin:

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

Hati-hati karena akan menghasilkan angka untuk setiap jalur input (meskipun mengabaikan nilai sebelumnya jika dikirim ke terminal).

Atau Anda dapat menerapkan tail -fdengan tangan di shell:

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

(perhatikan bahwa ia menjalankan hingga satu wcdan satu sleepperintah per detik yang tidak semua shell memiliki built-in. Dengan ksh93sementara sleepbuiltin, untuk mendapatkan built in wc(setidaknya pada Debian), Anda perlu menambahkan /opt/ast/bindi bagian depan $PATH(terlepas dari apakah direktori itu ada atau tidak) atau gunakan command /opt/ast/bin/wc(jangan tanya ...)).

Anda dapat menggunakan pv, seperti pada:

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

Namun berhati-hatilah bahwa itu menambahkan k, M... sufiks ketika jumlahnya lebih dari 1000 (dan sepertinya tidak ada cara lain ).

Stéphane Chazelas
sumber
Whow untuk tail | awksolusi Anda . Ketahui opsi Anda: -n +0tidak akan terpikir oleh saya dalam kombinasi ini.
towi
2
wah! pv- Alat baru lain yang bermanfaat. terima kasih banyak.
towi
Dengan grep Anda dapat menambahkan filter ke aliran Anda:tail -n +0 -f <my.log> | grep --line-buffered <mystring> | awk '{printf "\r%lu", NR}'
tombolinux
2
@tombolinux, awkadalah superset dari grep. tail -n +0 -f file | awk '/mystring/ {printf "\r%lu", ++n}'
Stéphane Chazelas
Keren. Saya menambahkan END{print ""}untuk membuat awkcetak baris baru di akhir.
pLumo
6

Coba hitung dengan murni bashtanpa wc:

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

atau bahkan seperti ini untuk menulis ulang nilai sebelumnya:

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

Saya tidak percaya ada yang seperti itu. Tetapi semestinya mudah untuk menyiapkan sesuatu seperti:

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

(Gagasan umum dari perlfunc(1))

vonbrand
sumber
1
Jumlahnya akan bertambah setiap kali Anda melakukan a printf foo >> file. Anda harus menghitung karakter baris baru (seperti yang wc -ldilakukan dalam solusi shell yang saya sarankan), bukan catatan yang dikembalikan oleh <$fh>. Saya tidak berpikir Anda perlu menggunakan tellatau seeksama sekali.
Stéphane Chazelas
The <$fh>membaca garis secara default, tidak mencatat. Halaman manual Perl yang dikutip memberi tahu untuk melakukannya dengan cara ini demi lingkungan yang mungkin tidak kooperatif (bisa bergantung pada sistem file, saya kira NFS atau sistem file yang dipasang di jaringan lainnya mungkin memerlukan sedikit dorongan).
vonbrand
Cobalah sendiri, setelah mencapai akhir file, <$fh>akan mengembalikan catatan meskipun tidak diakhiri oleh karakter baris baru. Jadi jika perlduduk di akhir file, dan seseorang kemudian melakukan printf foo >> file, maka <$fh>akan kembali foo(bukan baris karena tidak dihentikan oleh karakter baris baru), dan $countakan bertambah meskipun tidak ada garis tambahan yang ditambahkan ke file.
Stéphane Chazelas
OP seharusnya memantau file log yang ditulis satu baris pada suatu waktu?
vonbrand
Tidak, itu sebabnya solusi Anda mungkin tidak berfungsi. Sebagai contoh, jika aplikasi menulis ke file buffer outputnya, maka pada waktu tertentu, baris terakhir kemungkinan tidak akan dihentikan sehingga akan dihitung dua kali.
Stéphane Chazelas
0

Melanjutkan solusi berbasis awk: Anda mungkin tidak perlu melihat penghitung berdetik untuk setiap baris dalam log Anda; itu masalahnya, Anda dapat memilikinya seperti ini (nomor akan berubah untuk setiap 10 baris):

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