我捕获了使用 tput 在屏幕上绘制某些内容的脚本的输出。当我执行 cat myoutput 时,一切都很清楚(看起来终端从头开始重新解释它),但是当我编辑或管道输出时,我看到大量的 ansi 序列以及破坏性打印之前的所有内容,例如 tput clear 等。
我怎样才能对其进行后处理,以便我只得到最终的“渲染”?
更好的是,其根源是我目前正在编写我的脚本,因此它将除了终端之外的所有内容都打印到文件中
和exec > >(tee /dev/tty)
有没有办法告诉标准输出通道在保存之前“渲染”所有内容?
答案1
你想要的是一个程序明白这些终端控制序列,并且能够渲染最终视图。那么,这样的程序称为终端仿真器。其中一些是图形化的——比如您启动使用 shell 的程序,例如 gnome-terminal 或 alacritty,其他的主要是无头的。
较古老的screen
或更现代的tmux
都是这里的相关内容。
- 写一个“外部”脚本:
- 创建命名管道
tmux
在后台启动您的“内部”脚本(即输出内容的脚本)- 在你的外部脚本中,从 fifo 读取(这会阻塞,因为没有写入任何内容),
- 读取完成后,指示
tmux
输出屏幕截图
- 在您的内部脚本中,向命名管道写入一些内容以表明您处于要截取屏幕截图的状态
把它放在一起,就像
#!/usr/bin/zsh
# outer script
# SPDX-License-Identifier: WTFPL
# Make a temporary directory
tmpdir="$(mktemp -d)"
# Prepare the FIFO
fifo="${tmpdir}/fifo"
mkfifo "${fifo}"
# Start the inner script in tmux
tmux new-session -d -s "${tmpdir}" -e "FIFO=${fifo}" ./inner-script.sh …
#^ ^ ^ ^------+-----^ ^------+--------^ ^ ^
#| | | | | | |
#\------run tmux, the terminal emulator
# | | | | | |
# \---in tmux, run the "new-session" command to, well, get a new session
# | | | | |
# \---detach that session, i.e. *don't* connect it to the current terminal
# | | | |
# \--specify the session name. Conveniently, we abuse the name
# of our temporary directory, as it's inherently unique
# | | |
# \-- for the started command, set the environment
# variable FIFO to the name of our FIFO
# | |
# \-- launch your script
# …with its arguments--/
# Wait for something to be written to our FIFO
cat "${fifo}" > /dev/null
# instruct tmux to take a "pane shot"
tmux capture-pane -t "${tmpdir}" -p > "/path/to/capture"
# ^------+-----^ ^ ^---------+--------^
# | | |
# \-------------------------------- target (session name as above)
# | |
# \----------------------- print to stdout
# |
# \----------- redirect stdout to file
# Finally, clean up session and temporary directory
tmux kill-session -t "${tmpdir}"
rm -rf "${tmpdir}"
您只需要将写入的内容添加到 fifo 中inner-script.sh
,例如echo done > "${FIFO}"; sleep 100
.
如果您已经有“记录”输出,您inner-script.sh
可能只是cat recording.txt; echo done > "${FIFO}"; sleep 100