计算上一个程序的输出行数


32

我正在尝试计算某个程序产生的输出行数。问题是,该程序需要很长时间才能运行,并且我想向用户显示输出。有没有一种方法可以计算最后一条命令输出的行数?

我可以,program | wc -l但是不会向用户显示输出。据我所知,我必须做program; program | wc -l-但是该程序至少需要一分钟才能运行,所以我不想只为了在底部显示行数就要做一次以上。

编辑:

  • 有没有一种方法可以显示输出(逐行显示),然后在末尾返回计数?

怎么样:让程序跟踪自己的输出,只从变量STDOUT_WRITE_COUNT末尾读取该值(例如),或在程序末尾将其记录到文件/ API中。WDYT?
mecampbellsoup

Answers:


43

您可以像平常一样使用tee拆分输出流,将一个副本发送到另一副本,wc并将另一个副本发送到STDOUT。

program | tee >(wc -l)

>(cmd)是bash的语法该装置运行cmd和替换>(cmd)用的路径(连接到一个命名管道),该程序的STDIN位。


2
>(cmd)ksh语法也可以被zsh和识别,并且bash仅在没有语法的系统上使用命名管道/dev/fd/n
斯特凡Chazelas

@StephaneChazelas是的,大多数外壳程序都支持它,但是它不在POSIX中,因此不能依赖它在任何地方。
Patrick

是的,我只是指出流程替代不是一项bash发明,因为您回答中的措辞可能让人相信。
斯特凡Chazelas

1
@TheLibbster取决于您如何定义高效。此方法确实包含产生2个其他进程,其中as sed和as awk只是一个。但是teewc都非常小(比sed和小得多awk)。
Patrick

1
@TheLibbster是的,根据我刚刚做的一些简单测试,它实际上是sedawk方法的两倍。(我将dd100mb /dev/urandom写入文件,然后通过每种方法多次运行该文件)
Patrick

10

一种选择是使用awk,它可以进行计数并打印到stdout。

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

在中awk,NR是当前行号。您可以使用perl完成相同的操作:

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

sed

program | sed -n 'p;$='

有没有一种方法可以显示输出(逐行显示),然后在末尾返回计数?
Libbux

6

您可以在stderr上克隆stdout。

program | tee /dev/stderr | wc -l

这样,programtee可以将的stdout通过管道传输到stderr,后者将打印在控制台上。tee还将通过管道传输到其的数据写入通过管道传输到的标准输出wc


3

我最喜欢的选择:

program | grep "" -c

1
OP可能会问其他问题,但是我来这里只是想获得输出的行数,并不关心显示实际的输出,因此就可以了。谢谢!
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,将报告行数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.