示例:我用
script
开始录音,并尝试输入 echo test
但省略了 o,所以我退格来纠正它。
当我
cat typescript
一切看起来正常,因为代码被解释,但如果我使用less
或vim
我看到ech test^H^[[K^H^[[K^H^[[K^H^[[K^H^[[Ko test^M
我完全理解这是什么以及为什么会发生,但是有没有办法“烧入”代码并只在文件中查看结果?我的笨拙方法是
cat
文件,然后将文本复制/粘贴到终端之外,但肯定 cat、sed、awk 或其他东西的某种组合可以更轻松地让我到达那里?
要显示包含 ANSI 序列的文件,
less -r typescript
或者,
less -R typescript
要从文件中删除 ANSI 和退格序列,创建一个干净的
newfile
,请尝试:
sed -r ':again; s/[^\x08]\x08\x1b\[K//; t again; s/\x1b_[^\x1b]*\x1b[\]//g; s/\x1B\[[^m]*m//g' typescript >newfile
-r
这将打开扩展正则表达式。 (在 BSD 系统上,
-r
应替换为 -E
。现代版本的 GNU sed 将接受 -r
或 -E
。)`:再次; s/[^\x08]\x08\x1b[K//;又来了
这会删除所有退格序列。这些都是在循环中一次完成一个。
s/\x1b_[^\x1b]*\x1b[\]//g
作为
xterm
扩展(请参阅文档),Esc _ something Esc \
不会执行任何操作。此命令删除这些序列。s/\x1B\[[^m]*m//g
这会删除设置颜色等的剩余 ANSI 序列。
这涵盖了我通常遇到的所有控制序列。有各种各样的扩展控制序列,如果您的输出中有一些我没有见过的,则代码可能需要扩展。
sed
在 BSD 或 POSIX 系统上,各个命令必须使用
-e
选项而不是分号链接在一起。因此,尝试:
sed -e ':again' -e 's/[^\x08]\x08\x1b\[K//' -e 't again' -e 's/\x1b_[^\x1b]*\x1b[\]//g' -e 's/\x1B\[[^m]*m//g'
使用“sed -r”的建议答案依赖于 GNU sed,这使得它不能真正移植。可以使用 POSIX sed 执行相同的功能,但有所不同:POSIX 不提供在命令选项中传递整个脚本的功能,如此处所示。这意味着实现循环的 (POSIX) 方法将位于一个单独的文件中,并使用“-f”选项传递给 sed。同样,十六进制常量也是不可移植的。进行这些更改后,可以在 BSD 和 Unix 系统上使用功能等效的脚本。
建议的答案也没有涵盖一些相当常见的回车符的用法(例如在 yum 输出中),也没有过滤掉“大多数”ANSI 序列(因为它专注于 SGR“m”最终字符) 。最后,它指的是
escape _ text _
作为 xterm 扩展。但 xterm 没有提供这样的扩展,因为两个字符“escape”和“_”开始一个 Application Program Command 序列(并且 xterm 没有实现)。
生成的 sed 脚本如下所示(“^[”是转义字符):
s/^[[[][<=>?]\{0,1\}[;0-9]*[@-~]//g
s/^[[]][^^[]*^G//g
s/^[[]][^^[]*^[\\//g
:loop
s/[^^H]^H\(.\)/\1/g
t loop
s/^M^M*$//g
s/^.*^M//g
s/^[[^[]//g
可以在here找到更完整的脚本,名为“script2log”。然而,有些东西(例如 CSI K)不适合 sed 脚本。
我想专门使用
pyte
来完成此任务。
import pyte
typescript_path = "mytypescript.log"
output_path = "typescript_plain.log"
# Specify the desired screen dimensions (columns x rows)
columns = 80 # please remember the columns for godsake.
# if you think it would be slow, use pypy instead.
rows = 100000 # what could go wrong now?
# Create a Screen object with the specified dimensions
screen = pyte.Screen(columns, rows)
# Create a ByteStream to handle ANSI control codes
stream = pyte.ByteStream(screen)
typescript_bytes = open(typescript_path,'rb').read()
# Insert ANSI control codes
stream.feed(typescript_bytes)
# Get the content with ANSI control codes
content = screen.display
plain_content ="\n".join(content).strip()
# Write the content to a file
with open(output_path, "w+") as file:
file.write(plain_content)