Подсчитать количество строк вывода из предыдущей программы

32

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

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

РЕДАКТИРОВАТЬ:

  • Есть ли способ показать вывод, как это происходит (строка за строкой), а затем вернуть счет в конце?
Libbux
источник
Как насчет того, чтобы программа отслеживала свой собственный вывод и просто считывала это значение из переменной (например 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методы, и методы. (Я ddзаписал 100 МБ /dev/urandomв файл, а затем несколько раз прогонял этот файл через каждый метод)
Патрик
10

Одним из вариантов является использование awk, который может выполнять подсчет и выводить на стандартный вывод.

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

В awk, NR - текущий номер строки. Вы можете сделать то же самое с Perl:

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

Или sed:

program | sed -n 'p;$='
jordanm
источник
Есть ли способ показать вывод, как это происходит (строка за строкой), а затем вернуть счет в конце?
Libbux
6

Вы можете клонировать стандартный вывод на стандартный вывод.

program | tee /dev/stderr | wc -l

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


источник
3

мой любимый вариант:

program | grep "" -c
montells
источник
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)
Zlob
источник
0

Это может быть поздно. Но я бы просто ответил на ваш вопрос о том, как поймать подсчитанное число в переменной.

Это то, что вы хотите YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l).

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

huangzonghao
источник