`wc -l` 显示计数的替代方法,因为它接收行

Pee*_*aha 3 performance shell io wc

wc -l用来计算命令输出中的行数,因为输入是通过管道传输到它的。

commad | wc -l
Run Code Online (Sandbox Code Playgroud)

这工作正常,但如果command正在进行一些繁重的计算,这很慢。是否有替代方法可以显示“到目前为止已通过管道输入”的行数?

当我在做一种每项计算时,这样的事情会特别有用,比如

cat something | xargs -L1 heavy-per-line-computation | wc -l
Run Code Online (Sandbox Code Playgroud)

我可以手动执行此操作的一种方法是将输出通过管道传输到文件 ( command > file) 并定期对其进行cat file | wc -l处理。但是一个单一的命令(它不重定向到文件,以避免浪费的 I/O),就是我所追求的。

Kam*_*ski 7

awk '{print NR}'
Run Code Online (Sandbox Code Playgroud)

此命令为遇到的每一行打印一个新数字。如果最后一行是完整的,那么最后一个数字将与所说的一致wc -l。如果最后一行不完整,那么awk可能会计算它(在我的 Kubuntu GNUawk中)但wc -l不会(因为它确实计算换行符);所以可能会有偏差。

另一个差异是如果输入完全为空:wc -l将打印0,我们awk将不打印任何内容。要使其打印0使用此变体:

awk '{print NR} END {if (NR==0) print NR}'
Run Code Online (Sandbox Code Playgroud)

或者,您可能希望每个新数字都覆盖控制台同一行中的旧数字。然后这个:

awk '{printf "\r%s",NR} END {print "\r"NR}'
Run Code Online (Sandbox Code Playgroud)

例子: yes | head -n 76543 | awk '{printf "\r%s",NR} END {print "\r"NR}'

请注意,该命令会消耗其输入(tee可能很方便)。出于监控目的,您可能对以下内容感兴趣:

awk '{print NR OFS $0}'
Run Code Online (Sandbox Code Playgroud)

其中(默认OFS为空格)几乎就像cat -n(如果您cat支持-n)。


pv -l计数线,它可以在管道内使用。例子:

for i in 1 2 3 4 5; do date; sleep 1; done | pv -l | wc -l
Run Code Online (Sandbox Code Playgroud)

考虑pv -lb非常小的输出。