我必须在后台运行第三方程序并将其输出捕获到文件。我只是简单地使用the_program > output.txt
来做这件事。然而,所述程序的编码器决定浮华并实时显示处理过的行,使用\b
字符来擦除先前的值。因此,output.txt中的一行最终会像Lines: 1(b)2(b)3(b)4(b)5
一样,(b)
是一个带有ASCII代码08
的不可打印字符。我希望该行最终为Lines: 5
。
我知道我可以按原样编写并对文件using AWK进行后处理,但我想知道是否有可能以某种方式处理控制字符,通过使用某种shell选项或将一些命令组合在一起,这样该行就会变成Lines: 5
,而不必在程序完成后运行任何其他命令?
修改
只是澄清一下:我在这里写的是一个简化版本,程序处理的实际行数是十万,所以字符串结尾很长。
答案 0 :(得分:2)
感谢您的评论!我最终将该程序的输出传递给问题中链接的AWK Script I.我最终得到了一个结构良好的文件。
the_program | ./awk_crush.sh > output.txt
唯一的缺点是,只有在程序本身完成后才能获得输出,即使初始输出超过5M并且应该在较小的块中传递。我不知道确切的原因,也许AWK脚本在stdin上等待EOF。无论哪种方式,在更现代的系统上我会使用
stdbuf -oL the_program | ./awk_crush.sh > output.txt
逐行处理输出。我虽然支持过期支持RHEL4,但我无法同时使用stdbuf
和unbuffer
。我会保持原样,也没关系。
awk_crush.sh的内容基于this answer,除了^H
序列(应该是通过VIM命令输入的ASCII 08
字符)替换为转义序列{{ 1}}:
\b
基本上,它用空字符串替换#!/usr/bin/awk -f
function crushify(data) {
while (data ~ /[^\b]\b/) {
gsub(/[^\b]\b/, "", data)
}
print data
}
crushify($0)
和\b
本身之前的字符,并在字符串中有\b
时重复它 - 正是我需要的。它并不关心其他的转义序列,但如果有必要的话,还有一个更完整的SED solution来自 Thomas Dickey 。