如何使用 Linux shell 脚本删除 ^[ 以及文件中的所有 ANSI 转义序列

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

我们想要删除

^[
以及所有转义序列。

sed 无法工作并给我们这个错误:

$ sed 's/^[//g' oldfile > newfile; mv newfile oldfile;
sed: -e expression #1, char 7: unterminated `s' command

$ sed -i '' -e 's/^[//g' somefile
sed: -e expression #1, char 7: unterminated `s' command
linux shell scripting
14个回答
70
投票

您在寻找ansifilter吗?


你可以做两件事:输入文字转义符(在 bash 中:)

使用键盘输入:

sed 's/Ctrl-vEsc//g'

或者

sed 's/Ctrl-vCtrl-[//g'

或者您可以使用字符转义:

sed 's/\x1b//g'

或对于所有控制字符:

sed 's/[\x01-\x1F\x7F]//g' # NOTE: zaps TAB character too!

61
投票

commandlinefu 给出正确答案,它会去除 ANSI 颜色以及移动命令:

sed "s,\x1B\[[0-9;]*[a-zA-Z],,g"

22
投票

出于我的目的,我管理了以下内容,但这不包括所有可能的 ANSI 转义

sed -r 's/\x1b\[[0-9;]*m?//g'

这会删除

m
命令,但对于所有转义(如 @lethalman 所评论),请使用:

sed -r 's/\x1b\[[^@-~]*[@-~]//g'

另请参阅“https://stackoverflow.com/questions/7857352/python-regex-to-match-vt100-escape-sequences”。

还有一个常见转义序列表


18
投票

ansi2txt 命令(kbtin 包的一部分)似乎在 Ubuntu 上完美地完成了这项工作。


12
投票

我没有足够的声誉来向 Luke H 给出的 answer 添加评论,但我确实想分享我一直用来消除所有 ASCII 转义序列的正则表达式。

sed -r 's~\x01?(\x1B\(B)?\x1B\[([0-9;]*)?[JKmsu]\x02?~~g'

11
投票

我在寻找一种从手册页中删除额外格式的方法时偶然发现了这篇文章。 ansifilter 做到了,但它与预期的结果相去甚远(例如,所有先前的粗体字符都被重复,如

SSYYNNOOPPSSIISS
)。

对于该任务,正确的命令是

col -bx
,例如:

groff -man -Tascii fopen.3 | col -bx > fopen.3.txt

(来源)

为什么这有效:(回应@AttRigh的评论)

groff
产生粗体字符,就像在打字机上一样:打印一个字母,用退格键向后移动一个字符(您无法擦除打字机上的文本),再次打印相同的字母以使字符更明显。因此,简单地省略退格键会产生“SSYYNNOOPPSSIISS”。
col -b
通过正确解释退格键修复了这个问题,引用手册:

-b 不输出任何退格键,仅打印写入每列位置的最后一个字符。


10
投票

您可以使用以下命令删除所有不可打印的字符:

sed 's/[^[:print:]]//g'


6
投票

我为此构建了vtclean。它按顺序使用这些正则表达式去除转义序列(在regex.txt中解释):

// handles long-form RGB codes
^\033](\d+);([^\033]+)\033\\

// excludes non-movement/color codes
^\033(\[[^a-zA-Z0-9@\?]+|[\(\)]).

// parses movement and color codes
^\033([\[\]]([\d\?]+)?(;[\d\?]+)*)?(.)`)

它还进行基本的行编辑模拟,因此可以解析退格键和其他移动字符(如左箭头键)。


4
投票
基于

sed
的方法,无需通过
-r

启用扩展正则表达式
sed 's/\x1B\[[0-9;]*[JKmsu]//g'

3
投票

只是一个注释;假设您有一个这样的文件(此类行结尾是由

git
远程报告生成的):

echo -e "remote: * 27625a8 (HEAD, master) 1st git commit\x1b[K
remote: \x1b[K
remote: \x1b[K
remote: \x1b[K
remote: \x1b[K
remote: \x1b[K
remote: Current branch master is up to date.\x1b[K" > chartest.txt

在二进制中,这看起来像这样:

$ cat chartest.txt | hexdump -C
00000000  72 65 6d 6f 74 65 3a 20  2a 20 32 37 36 32 35 61  |remote: * 27625a|
00000010  38 20 28 48 45 41 44 2c  20 6d 61 73 74 65 72 29  |8 (HEAD, master)|
00000020  20 31 73 74 20 67 69 74  20 63 6f 6d 6d 69 74 1b  | 1st git commit.|
00000030  5b 4b 0a 72 65 6d 6f 74  65 3a 20 1b 5b 4b 0a 72  |[K.remote: .[K.r|
00000040  65 6d 6f 74 65 3a 20 1b  5b 4b 0a 72 65 6d 6f 74  |emote: .[K.remot|
00000050  65 3a 20 1b 5b 4b 0a 72  65 6d 6f 74 65 3a 20 1b  |e: .[K.remote: .|
00000060  5b 4b 0a 72 65 6d 6f 74  65 3a 20 1b 5b 4b 0a 72  |[K.remote: .[K.r|
00000070  65 6d 6f 74 65 3a 20 43  75 72 72 65 6e 74 20 62  |emote: Current b|
00000080  72 61 6e 63 68 20 6d 61  73 74 65 72 20 69 73 20  |ranch master is |
00000090  75 70 20 74 6f 20 64 61  74 65 2e 1b 5b 4b 0a     |up to date..[K.|
0000009f

可以看到,

git
这里在行尾(
0x1b
)之前添加了序列
0x5b
0x4b
0x0a

请注意 - 虽然您可以在 sed 中将

0x1b
与文字格式
\x1b
匹配,但您不能对
0x5b
执行相同操作,它代表左方括号
[
:

$ cat chartest.txt | sed 's/\x1b\x5b//g' | hexdump -C
sed: -e expression #1, char 13: Invalid regular expression

您可能认为可以使用额外的反斜杠

\
来转义表示形式 - 最终结果为
\\x5b
;但是虽然“通过了”-但它与预期的任何内容都不匹配:

$ cat chartest.txt | sed 's/\x1b\\x5b//g' | hexdump -C
00000000  72 65 6d 6f 74 65 3a 20  2a 20 32 37 36 32 35 61  |remote: * 27625a|
00000010  38 20 28 48 45 41 44 2c  20 6d 61 73 74 65 72 29  |8 (HEAD, master)|
00000020  20 31 73 74 20 67 69 74  20 63 6f 6d 6d 69 74 1b  | 1st git commit.|
00000030  5b 4b 0a 72 65 6d 6f 74  65 3a 20 1b 5b 4b 0a 72  |[K.remote: .[K.r|
00000040  65 6d 6f 74 65 3a 20 1b  5b 4b 0a 72 65 6d 6f 74  |emote: .[K.remot|
...

因此,如果你想匹配这个字符,显然你必须将其写为转义的左方括号,即

\[
- 其余的值可以使用转义的
\x
表示法输入:

$ cat chartest.txt | sed 's/\x1b\[\x4b//g' | hexdump -C
00000000  72 65 6d 6f 74 65 3a 20  2a 20 32 37 36 32 35 61  |remote: * 27625a|
00000010  38 20 28 48 45 41 44 2c  20 6d 61 73 74 65 72 29  |8 (HEAD, master)|
00000020  20 31 73 74 20 67 69 74  20 63 6f 6d 6d 69 74 0a  | 1st git commit.|
00000030  72 65 6d 6f 74 65 3a 20  0a 72 65 6d 6f 74 65 3a  |remote: .remote:|
00000040  20 0a 72 65 6d 6f 74 65  3a 20 0a 72 65 6d 6f 74  | .remote: .remot|
00000050  65 3a 20 0a 72 65 6d 6f  74 65 3a 20 0a 72 65 6d  |e: .remote: .rem|
00000060  6f 74 65 3a 20 43 75 72  72 65 6e 74 20 62 72 61  |ote: Current bra|
00000070  6e 63 68 20 6d 61 73 74  65 72 20 69 73 20 75 70  |nch master is up|
00000080  20 74 6f 20 64 61 74 65  2e 0a                    | to date..|
0000008a

2
投票

Tom Hale 的回答留下了不需要的代码,但这是一个很好的工作基础。添加额外的过滤清除剩余的、不需要的代码:

sed -e "s,^[[[(][0-9;?]*[a-zA-Z],,g" \
    -e "s/^[[[][0-9][0-9]*[@]//" \
    -e "s/^[[=0-9]<[^>]*>//" \
    -e "s/^[[)][0-9]//" \
    -e "s/.^H//g" \
    -e "s/^M//g" \
    -e "s/^^H//" \
        file.dirty > file.clean

由于这是在非 GNU 版本的 sed 上完成的,您可以在其中看到

^[
^H
^M
,因此我使用了 Ctrl-V 、Ctrl-V Ctrl-H 和 Ctrl-V Ctrl-分别为M。
^>
实际上是克拉 (^) 和大于字符,而不是 Ctrl-<.

当时使用的是 TERM=xterm。

要删除 PCL 代码,请添加如下模式:

sed -e "s/^[[&()*][a-z]*[-+]*[0-9][0-9]*[A-Z]//" \
    -e "s/^[[=9EZYz]//" \
        file.dirty > file.clean

理想情况下,如果正则表达式与理解 ? 元字符的解释器一起使用,则第一个模式更好地表示为:

      "s/^[[&()*][a-z]?[-+]?[0-9][0-9]*[A-Z]//" \

1
投票

我一直使用的 bash 片段来去除(至少一些)ANSI 颜色:

shopt -s extglob
while IFS='' read -r line; do
  echo "${line//$'\x1b'\[*([0-9;])[Km]/}"
done

1
投票

我的回答

jenkins 在我们的日志中填充的这些奇怪的 ha:// URL 是什么?

有效地从 Jenkins 控制台日志文件中删除所有 ANSI 转义序列(它还处理 Jenkins 特定的 URL,这与此处不相关)。

我感谢并感谢 Marius Gedminaspyjama 在制定最终解决方案方面做出的贡献。


1
投票

这个简单的 awk 解决方案对我有用,试试这个:

str="happy $(tput setaf 1)new$(tput sgr0) year!" #colored text
echo $str | awk '{gsub("(.\\[[0-9]+m|.\\(..\\[m)","",$0)}1' #remove ansi colors
© www.soinside.com 2019 - 2024. All rights reserved.