`wc -l` 替代方案在接收行时显示计数

`wc -l` 替代方案在接收行时显示计数

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

commad | wc -l

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

当我进行某种逐项计算时,这样的事情特别有用,例如

cat something | xargs -L1 heavy-per-line-computation | wc -l

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

答案1

awk '{print NR}'

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

另一个差异是如果输入完全为空:wc -lwill print 0,我们的awkwill 不打印任何内容。要使其打印,0请使用以下变体:

awk '{print NR} END {if (NR==0) print NR}'

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

awk '{printf "\r%s",NR} END {print "\r"NR}'

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

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

awk '{print NR OFS $0}'

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


pv -l计算行数并且可以在管道内使用。例子:

for i in 1 2 3 4 5; do date; sleep 1; done | pv -l | wc -l

考虑pv -lb相当小的输出。

答案2

这是使用 Ruby 的解决方案。

count_linesstderr最多每半秒打印一次(通过)迄今为止收到的行数,并在最后打印总行数(通过stdout)。

read -d '' make_lines <<'EOF'
  STDOUT.sync = true
  [0.2, 0.1, 0.5, 0.1, 0.6, 0.1, 0.3, 0.1, 0.3, 0.01, 0.01].each do |t|
    puts
    sleep t
  end
EOF

read -d '' count_lines <<'EOF'
  lines = 0
  t = 0
  while gets do
    lines += 1
    now = Time.now.to_f
    if now - t > 0.5
      warn lines
      t = now
    end
  end
  puts lines
EOF

ruby -e "$make_lines" | ruby -e "$count_lines"

答案3

我认为您正在寻找pv(管道视图):

seq 100000000000 | pv -l | wc -l

答案4

大多数终端都是CR (\r)“移至第 1 列”。这允许您继续覆盖以前的输出。

dwc这是一个将从标准输入(可以是tail -f文件或输出进程替换)读取的脚本。脚本中有一个示例测试台。

这需要一个-l选择。默认情况下,将输入行号打印到终端中的当前行,为六位数字。使用 时-l,它还会打印收到的最后一行的前 60 个字符,并清除以前的任何文本。当它看到 EOF 时,它会发出换行符,因此提示出现在最后一个输出的下方。

#! /bin/bash

#.. dwc [-l]

AWK_SHORT='
BEGIN { Fmt = "\r%6d "; }
{ printf (Fmt, NR); }
END { printf ("\n"); }
'

AWK_LONG='
BEGIN { Fmt = "\r%6d  %.60s"; Clr = sprintf ("%60s", ""); }
{ printf (Fmt, NR, $0 Clr); }
END { printf ("\n"); }
'
    if [[ "${1}" = "-l" ]]; then
        awk "${AWK_LONG}"
    else
        awk "${AWK_SHORT}"
    fi

    exit

    #.. Test method.
    man ls | head -n 40 |
         while IFS='' read X; do
             printf '%s\n' "${X}"; sleep 0.75
         done |
         tee >( ./dwc -l ) > foo.txt

相关内容