Як зробити нескінченний 'wc -l' з gnu texttools?


28

Я, звичайно, це знаю

cat logfile.txt | wc -l
120

підкаже кількість рядків у файлі.

Тоді як

tail -f logfile.txt

покаже мені нові рядки, до яких пише інша програма logfile.txt.

Чи можливо комбінувати обидва, щоб я отримав постійне оновлення кількості рядків logfile.txt зі стандартними текстовими утилітами?

Я про це знаю

watch wc -l logfile.txt

але я не хочу кожен раз перераховувати весь файл, це здається марною. Потрібно буде додавати лише підрахунок щосекунди або, можливо, \rзамість а \nв кінці рядка.


1
Ваш файл такий великий, що переказування всього - це проблема? З точки зору відходів: catвихід трубопроводів - wcце також великий відхід !!
Бернхард

Так, він потенційно дуже великий.
букси

Відповіді:


36

Можливо:

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

(Зверніть увагу , що він працює до одного wcі однієї sleepкоманди в секунду, не всі снаряди побудували. З в ksh93той час як sleepце вбудовані, щоб отримати вбудований wc(принаймні , на Debian), вам потрібно додати /opt/ast/binв передній частині $PATH(незалежно від того , цей каталог існує чи немає) або використовувати command /opt/ast/bin/wc(не питати ...)).

Ви можете використовувати pv, як у:

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

Але майте на увазі, що він додає k, M... суфікси, коли кількість перевищує 1000 (і , здається, це не обійдеться ).


Хто до вашого tail | awkрішення. Знайте свої варіанти: -n +0не траплялося б мені в цьому поєднанні.
букси

2
хто! pv- ще один корисний новий інструмент. дякую купу.
букси

За допомогою grep ви можете додати фільтр у свій потік:tail -n +0 -f <my.log> | grep --line-buffered <mystring> | awk '{printf "\r%lu", NR}'
tombolinux

2
@tombolinux, awkце супернабір grep. tail -n +0 -f file | awk '/mystring/ {printf "\r%lu", ++n}'
Стефан Шазелас

Класно. Додаю, END{print ""}щоб зробити awkдрук нового рядка наприкінці.
pLumo

6

Спробуйте порахувати це чистим 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

1

Я не вірю, що є щось подібне. Але потрібно легко пробити щось за принципом:

#!/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
Кількість збільшуватиметься кожного разу, коли ви робите це printf foo >> file. Вам потрібно буде порахувати символи нового рядка (як wc -lце робиться в оболонці, яке я запропонував), а не записи, повернуті ними <$fh>. Я не думаю, що вам потрібно використовувати tellабо seekвзагалі.
Стефан Шазелас

За <$fh>замовчуванням читається рядок, а не записується. Наведена сторінка Perl повідомляє про те, щоб зробити це таким чином заради можливо не співпрацюючого середовища (це може залежати від файлової системи, я думаю, що NFS або інші файлові системи, встановлені в мережі, можуть зажадати трохи випередження).
фонбранд

Спробуйте самі, досягаючи кінця файлу, <$fh>поверне запис, навіть якщо він не закінчується символом нового рядка. Отже, якщо perlвін сидить у кінці файлу, а хтось пізніше зробить a printf foo >> file, то <$fh>повернеться foo(не рядок, оскільки він не закінчується символом нового рядка), і $countвін буде нарощений, навіть не додавши до файлу жодної додаткової рядки.
Стефан Шазелас

ОП повинен був контролювати журнали, записані рядком за один раз?
vonbrand

Ні, тому ваше рішення може не спрацювати. Наприклад, якщо програми, що записують у файл, буферизують його вихід, то в будь-який момент часу останній рядок, ймовірно, не буде припинено, тому буде рахуватися двічі.
Стефан Шазелас

0

Продовжуючи рішення, засноване на awk: вам може не знадобитися бачити лічильник, який позначає кожен рядок у вашому журналі; це так, ви можете мати його так (число буде змінюватися на кожні 10 рядків):

tail -n +0 logfile.txt | \
    awk 'a+=1{}a%10==0{printf "\r%lu", a}END{printf "\r%lu", a}'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.