Як зробити нескінченний '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.