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