我有一个命令可以创建非常详细的输出,大约每秒数百行。但是,该命令用于\r
以类似于进度条的方式覆盖前一行输出。有时它会向终端写入换行符,这会“烘焙”当前的输出行。
将此输出重定向到文件时,我得到数百兆的输出 - 每行都写入文件,而不是在发生回车时被“覆盖”。
我知道这是预期的行为,解决这个问题的一种方法是让程序更智能,并意识到它正在被重定向到文件,而不是打印此交互状态。但是,我无法修改这个程序。
有什么方法可以管道/过滤此输出,以便最终输出文件中的内容与在终端上交互式运行它时看到的内容相同?
我试过了:
spammy_cr_command | uniq
...其输出与没有相同uniq
并且:
spammy_cr_command | sed '/\r/d'
...这也删除了包含换行符的“烘焙”行。
答案1
cmd | sed -e 's/.*\r//' > file
这会将每行上回车后的所有文本替换为空,只留下最后回车之后的部分行。这不是一定虽然与终端上留下的内容相同,但大多数时候它是一个近似值。
特别是,不处理行比其后继行长的情况。该程序会给出不正确的结果:
printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'
因为明显留下的是
xyzdefg
123456789
xyz
但sed
也会跳过所有未删除的字符并给出
xyz
xyz
您可以确定您的程序是否有这样的行为。进度条等将光标停留在左侧边缘的情况并不罕见,这可能不会给出您想要的结果。
答案2
对于非常原始的 TTY-37 输出,该命令解决了这个问题,而没有M. Homer 的答案中提到col
的问题。 sed
(对于不是简单 TTY-37 输出且包含终端转义和控制序列的输出,该工具col
也不sed
是该工作的工具;但 Stack Exchange 已在那已经快八年了。)
%( printf 'abcdefg\rxyz\n' printf '123456789\r\nxyz\n' )|列b xyz定义 123456789 XYZ %
答案3
可以使用 GNU awk 完成更接近覆盖行为的操作:
BEGIN {
RS = "[\r\n]" # split records on either CR or LF
a = "" # variable to save the text for overwriting
}
{
a = $0 substr(a, 1 + length) # save current line, add trailing part of saved text
}
RT ~ /\n/ { # LF, time to print and reset
print a;
a = ""
}
使用迈克尔·霍默的例子:
~ awk 'BEGIN { RS="[\r\n]" } {a = $0 substr(a, 1 + length)} RT ~ /\n/ {print a; a=""}' foo
xyzdefg
123456789
xyz
该变量需要 GNU awk ,它包含与该记录的正则表达式RT
匹配的记录分隔符文本。RS