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


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只是一个。但是tee和wc都非常小(比sed和小得多awk)。
— Patrick

1
@TheLibbster是的,根据我刚刚做的一些简单测试,它实际上是sed和awk方法的两倍。(我将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

这样,program就tee可以将的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.