我可以使用 unix utils 以编程方式将 ANSI 控制代码“烧入”文件吗?

问题描述 投票:0回答:3

示例:我用

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 或其他东西的某种组合可以更轻松地让我到达那里?

linux awk sed cat
3个回答
6
投票

要显示包含 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 序列。

这涵盖了我通常遇到的所有控制序列。有各种各样的扩展控制序列,如果您的输出中有一些我没有见过的,则代码可能需要扩展。

POSIX 或 BSD
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'

3
投票

使用“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 脚本。


0
投票

我想专门使用

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)
© www.soinside.com 2019 - 2024. All rights reserved.