Làm thế nào để thực hiện một 'wc -l' liên tục với các công cụ văn bản gnu?


28

Tôi biết tất nhiên rằng

cat logfile.txt | wc -l
120

sẽ cho tôi biết số lượng dòng trong một tập tin.

Trong khi

tail -f logfile.txt

sẽ chỉ cho tôi những dòng mới mà một chương trình khác viết logfile.txt.

Có thể kết hợp cả hai để tôi có được số lần cập nhật liên tục của logfile.txt với các tiện ích văn bản tiêu chuẩn không?

Tôi biết về

watch wc -l logfile.txt

nhưng tôi không muốn đếm lại toàn bộ tập tin mỗi lần, điều đó dường như là một sự lãng phí. Người ta sẽ cần một số chỉ được nối thêm mỗi giây hoặc lâu hơn và có thể \rthay vì \nở cuối dòng.


1
Là tập tin của bạn lớn mà kể lại tất cả mọi thứ là một vấn đề? Về chất thải: catsản lượng đường ống wccũng là một sự lãng phí lớn !!
Bernhard

Vâng, nó có khả năng là rất lớn.
Towi

Câu trả lời:


36

Có lẽ:

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

Coi chừng rằng nó sẽ xuất một số cho mỗi dòng đầu vào (mặc dù ghi đè giá trị trước đó nếu được gửi đến một thiết bị đầu cuối).

Hoặc bạn có thể thực hiện tail -fbằng tay trong shell:

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

(lưu ý rằng nó chạy lên đến một wcvà một sleeplệnh mỗi giây mà không phải tất cả vỏ đã được xây dựng trong. Với ksh93thời gian sleepđược dựng sẵn, để có được một xây dựng trong wc(ít nhất là trên Debian), bạn cần phải thêm /opt/ast/binở phía trước $PATH(bất kể thư mục đó có tồn tại hay không) hoặc sử dụng command /opt/ast/bin/wc(đừng hỏi ...)).

Bạn có thể sử dụng pv, như trong:

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

Nhưng hãy cẩn thận khi nó thêm vào k, M... hậu tố khi con số trên 1000 (và dường như không có cách nào khác ).


Whow để tail | awkgiải pháp của bạn . Biết lựa chọn của bạn: -n +0sẽ không xảy ra với tôi trong sự kết hợp này.
Towi

2
bất ngờ pv- một công cụ mới hữu ích khác. Cảm ơn nhiều.
Towi

Với grep, bạn có thể thêm bộ lọc vào luồng của mình:tail -n +0 -f <my.log> | grep --line-buffered <mystring> | awk '{printf "\r%lu", NR}'
Tombolinux

2
@tombolinux, awklà một superset của grep. tail -n +0 -f file | awk '/mystring/ {printf "\r%lu", ++n}'
Stéphane Chazelas

Mát mẻ. Tôi thêm END{print ""}vào để thực hiện awkin một dòng mới ở cuối.
pLumo

6

Hãy thử đếm nó với thuần túy bashmà không có wc:

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

hoặc thậm chí như thế này để viết lại giá trị trước đó:

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

1

Tôi không tin rằng có bất cứ điều gì như vậy. Nhưng nó sẽ dễ dàng để làm cho một cái gì đó dọc theo dòng:

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

(Ý tưởng chung được đưa ra từ perlfunc(1))


1
Số lượng sẽ tăng lên mỗi khi bạn làm a printf foo >> file. Bạn cần đếm các ký tự dòng mới (giống như wc -ltrong giải pháp shell tôi đã đề xuất), chứ không phải các bản ghi được trả về <$fh>. Tôi không nghĩ bạn cần sử dụng tellhay seekgì cả.
Stéphane Chazelas

Các <$fh>dòng đọc theo mặc định, không ghi. Trang chủ Perl được trích dẫn nói rằng hãy làm theo cách này vì lợi ích của một môi trường không hợp tác (có thể phụ thuộc vào hệ thống tệp, tôi đoán NFS hoặc các hệ thống tệp gắn trên mạng khác có thể cần một chút giả mạo).
vonbrand

Hãy tự mình thử, khi đến cuối tệp, <$fh>sẽ trả về một bản ghi ngay cả khi nó không bị chấm dứt bởi một ký tự dòng mới. Vì vậy, nếu perlngồi ở cuối tệp và sau đó ai đó sẽ thực hiện printf foo >> file, sau đó <$fh>sẽ trả về foo(không phải là một dòng vì nó không bị chấm dứt bởi một ký tự dòng mới) và $countsẽ được tăng lên ngay cả khi không có thêm dòng nào được thêm vào tệp.
Stéphane Chazelas

OP có nghĩa vụ giám sát logfiles viết một dòng tại một thời điểm?
vonbrand

Không, đó là lý do tại sao giải pháp của bạn có thể không hoạt động. Chẳng hạn, nếu các ứng dụng ghi vào tệp đệm bộ đệm đầu ra của nó, thì tại bất kỳ thời điểm nào, dòng cuối cùng có khả năng không bị chấm dứt nên sẽ được tính hai lần.
Stéphane Chazelas

0

Tiếp tục giải pháp dựa trên awk: bạn có thể không cần phải xem bộ đếm đánh dấu cho từng dòng trong nhật ký của bạn; đó là trường hợp, bạn có thể có nó như thế này (số sẽ thay đổi cho mỗi 10 dòng):

tail -n +0 logfile.txt | \
    awk 'a+=1{}a%10==0{printf "\r%lu", a}END{printf "\r%lu", a}'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.