从curl输出中提取下载进度

从curl输出中提取下载进度

我正在尝试提取 正在检索的文件的下载进度curl

我尝试了这个,但这不起作用:

curl --progress-bar http://127.0.0.1/test.tar.bz2 -o test.tar.bz2 2>/dev/stdout | sed -r 's/[# ]//g;s/^/#/g'

不过这个sed表达似乎没问题:

$ echo '########                      10.2%' | sed -r 's/[# ]//g;s/^/#/g'
#10.2%

谁能指出我做错了什么?

答案1

主要问题是sed适用于线因此,在到达第一个命令之前它不会执行任何操作\n,并且在您的命令完成之前不会发生这种情况。您可以通过将\rs 与s交换来解决此问题\n

$ curl --progress-bar http://127.0.0.1/test.tar.bz2 -o test.tar.bz2 2>&1 | 
   tr $'\r' $'\n' | sed -r 's/[# ]+/#/g;'

然而,这会给您带来缓冲,缓冲sed现在将作用于多组行。我一起破解的最终解决方案是将错误重定向到一个文件,然后处理该文件:

$ curl --progress-bar http://127.0.0.1/test.tar.bz2 -o test.tar.bz2 2>er
$ while :; do 
    echo -ne "$(tr $'\r' $'\n' < er | tail -n 1 | sed -r 's/^[# ]+/#/;')\r"; 
  done

上面的命令将解析错误文件(er)并打印结果并\r使其不断更新。您需要手动摆脱它。

来自匿名用户的建议:您还可以放在这些命令的stdbuf -oL前面trsed从而修改这些命令的缓冲行为。

答案2

尝试 perl:

curl --progress-bar http://127.0.0.1/test.tar.bz2 -o test.tar.bz2 2>&1 | perl -015 -n -e 'print "$1\n" if (/[#]* ([\d]+)/);'

在哪里:

  • 2>&1 将 stderr 分配给 stdout 所在的位置,在本例中是到 perl 的管道
  • -015 设置输入记录分隔符为回车符(八进制15)
  • -e 是一行代码,在本例中,它跳过任何前导 # 并将后续整数提取到 $1 中,只要提取成功,就会打印 $1 。
  • -n 将 -e 提供的行包装在“while(<>){}”中,逐条记录地读取输入,直到 EOF,其中我们安排每个记录用 CR 和 -0 分隔

相关内容