Порахуйте кількість рядків виходу з попередньої програми


32

Я намагаюся підрахувати кількість рядків виводу певної програми. Проблема в тому, що програма запускає тривалий час, і я хочу відобразити вихід користувачеві. Чи є спосіб підрахувати кількість рядків останньої виведеної команди?

Я міг би зробити, program | wc -lале це не показало б користувачеві вихід. Тож, наскільки я знаю, я маю це зробити program; program | wc -l- але для запуску програми потрібно хоча б хвилину, тому мені не хочеться робити це більше одного разу, щоб показати кількість рядків внизу.

Редагувати:

  • Чи існує спосіб відображення результату, як це відбувається (рядок за рядком), а потім повернення рахунку в кінці?

Як щодо: попросіть програму відслідковувати власний вихід і просто прочитати це значення зі змінної (наприклад STDOUT_WRITE_COUNT), або ввійти в файл / API в кінці програми. WDYT?
mecampbellsoup

Відповіді:


43

Ви можете використовувати teeдля розділення вихідного потоку, надсилаючи одну копію, wcа іншу - STDOUT як звичайну.

program | tee >(wc -l)

>(cmd)Є Баш синтаксису , який означає запустити cmdі замінити >(cmd)біт з шляхом (іменований канал , підключений до) STDIN цієї програми.


2
>(cmd)має kshсинтаксис також визнається zshі bashі тільки з використанням іменованих каналів в системах , які не мають /dev/fd/n.
Стефан Шазелас

@StephaneChazelas Так, більшість оболонок підтримує його, але це не в POSIX, тому на нього не можна покластися, щоб бути скрізь.
Патрік

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

1
@TheLibbster Залежить від ефективності визначення. Цей метод передбачає нерестування 2 додаткових процесів, де як sedі awkє лише один. Але teeі wcобидва надзвичайно малі (набагато менше , ніж sedта awk).
Патрік

1
@TheLibbster так, за деякими простими тестами, які я щойно робив, насправді це приблизно вдвічі швидше, як sedі awkметоди. (Я ddd 100mb /dev/urandomдо файлу, а потім запускав цей файл через кожен метод кілька разів)
Патрік

10

Один із варіантів - використовувати awk, який може робити підрахунок та друк для stdout.

program | awk '{ print } END { print NR }'

В awk, NR - номер поточного рядка. Ви можете виконати те ж саме за допомогою perl:

program | perl -pe 'END {print "$.\n"}'

Або sed:

program | sed -n 'p;$='

Чи існує спосіб відображення результату, як це відбувається (рядок за рядком), а потім повернення рахунку в кінці?
Ліббукс

6

Ви можете клонувати stdout на stderr.

program | tee /dev/stderr | wc -l

Таким чином, programstdout в трубі teeзаписується до stderr, який друкується на консолі. teeтакож записує дані, перекладені на нього, до його stdout, на який покладено wc.


3

мій улюблений варіант:

program | grep "" -c

1
ОП, можливо, попросив щось інше, але я прийшов сюди, шукаючи просто отримання підрахунку кількості рядків, і мені було все одно, що показує фактичний вихід, і це робить свою роботу. Спасибі!
Nikhil VJ

0
tail -f /var/log/squid/access.log | ( c=0; pl() { echo $c; c=0; }; trap pl SIGHUP; while read a; do (( c=c+1 )); done ) & ( trap 'kill $! ; exit' SIGINT; trap '' SIGHUP; while true; do kill -HUP $! ; sleep 1; done)

0

Це може бути пізно. Але я би просто звернувся до вашого подальшого питання про те, як зловити перелічене число у змінній.

Це те, що ти хочеш YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l).

Ми скористаємося teeгенеруванням тут двох потоків і направляємо один на /dev/stderr, який з’явиться на екрані, а другий на wc -l, який би повідомив про кількість рядків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.