Bash - 将输出重定向到文件时处理退格控制字符

Tim*_*ler 5 linux bash shell

我必须在后台运行第三方程序并将其输出捕获到文件中。我只是使用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程序完成后该行就无需运行任何其他命令了?

编辑:

只是澄清一下:我在这里写的是一个简化版本,程序处理的实际行数是十万,所以字符串最终很长。

Tim*_*ler 2

感谢您的意见!我最终将该程序的输出传输到我在问题中链接的 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 上,支持已过期,所以我无法使用stdbufunbuffer。我就保持原样,也很好。

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