web-dev-qa-db-ja.com

GNU textoolsで継続的な 'wc -l'を行う方法は?

もちろん知っている

cat logfile.txt | wc -l
120

ファイルの行数を教えてくれます。

一方

tail -f logfile.txt

別のプログラムがlogfile.txtに書き込む新しい行が表示されます。

両方を組み合わせて、標準のテキストユーティリティでlogfile.txtの継続的な更新行数を取得することは可能ですか?

私は知っています

watch wc -l logfile.txt

しかし、毎回ファイル全体を数え直したくないので、それは無駄です。行末に\rではなく、毎秒程度の追加のみのカウントが必要で、おそらく\nが必要です。

28
towi

多分:

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

入力のすべての行に数値を出力することに注意してください(ただし、端末に送信された場合は前の値をオーバーライドします)。

または、シェルでtail -fを手動で実装することもできます。

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

(1秒あたり最大1つのwcコマンドと1つのsleepコマンドが実行されることに注意してください。すべてのシェルが組み込まれているわけではありません。ksh93sleepが組み込まれていると、組み込みのwc(少なくともDebianでは)を取得するには、/opt/ast/bin$PATHの前に追加するか(そのディレクトリが存在するかどうかに関係なく)、またはcommand /opt/ast/bin/wc(聞かないでください...))。

次のように、pvを使用できます。

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

ただし、数値が1000を超えるとkM...のサフィックスが追加されることに注意してください(そして それを回避する方法はないようです )。

36

bashなしの純粋なwcでカウントしてみてください。

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

以前の値を書き換えるには、次のようにします。

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

そんなことあるとは思いません。しかし、次のように簡単に修正できます。

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

perlfunc(1)から引用された一般的なアイデア)

1
vonbrand

Awkベースのソリューションを続行します。ログの各行のカウンターのティックを確認する必要がない場合があります。その場合、次のようにすることができます(番号は10行ごとに変わります)。

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