我有一个包含(ANSI?)转义序列的文本文件:
当我cat
输入文件时,我得到格式化输出:
如何将文本文件的输出保存/通过管道传输到新文件,以便删除控制代码但保留格式?
换句话说,我想将文件的内容转换/导出到新文件,同时保留预期的显示格式(例如,就像使用时得到的那样less -r <file>
)。
我需要一种自动化的方法来执行此操作,以便可以记录输出并将其作为电子邮件通知发送。
这是上面屏幕截图中文件的 Base64 输出(用于base64 -d
解码它):
G1tIG1syShtbMTsxSA0KG1s0OzRIICAgICAgICAgICAgICAgICAgICAgICAgICBDT05GSURFTlRJ
QUwgSU5GT1JNQVRJT04bW0sbWzU7NEgbW0sbWzY7NEgbW0sbWzc7NEhUaGlzIHdvcmsgY29udGFp
bnMgdmFsdWFibGUsIGNvbmZpZGVudGlhbCwgYW5kIHByb3ByaWV0YXJ5IGluZm9ybWF0aW9uLhtb
SxtbODs0SERpc2Nsb3N1cmUsIHVzZSwgb3IgcmVwcm9kdWN0aW9uIGlzIGdvdmVybmVkIGJ5IHlv
dXIgTGljZW5zZSBBZ3JlZW1lbnQuG1tLG1sxMDs0SBtbSxtbMTE7NEhUaGlzIHVucHVibGlzaGVk
IHdvcmsgaXMgcHJvdGVjdGVkIGJ5IHRoZSBsYXdzIG9mIHRoZSBVbml0ZWQgU3RhdGVzIGFuZBtb
SxtbMTI7NEhvdGhlciBDb3VudHJpZXMuICBUaGUgd29yayB3YXMgY3JlYXRlZCBpbiAxOTg4IGFu
ZCByZXZpc2VkIGluIDE5OTQuICAbW0sbWzEzOzRISWYgcHVibGljYXRpb24gb2NjdXJzLCB0aGUg
Zm9sbG93aW5nIG5vdGljZSBzaGFsbCBhcHBseTobW0sbWzE0OzRIG1tLG1sxNTs0SBtbSxtbMTY7
NEggICBDb3B5cmlnaHQgMTk4OCwxOTk0LiBBbGwgcmlnaHRzIHJlc2VydmVkLhtbSxtbMTc7NEgb
W0sbWzE4OzRIG1tLG1sxOTs0SFRoaXMgQ29weXJpZ2h0IG5vdGljZSBhbmQgb3RoZXIgY29weXJp
Z2h0IG5vdGljZXMgaW5jbHVkZWQgaW4gdGhlIG1hY2hpbmUbW0sbWzIwOzRIcmVhZGFibGUgY29w
aWVzIG11c3QgYmUgcmVwcm9kdWNlZCBvbiBhbGwgYXV0aG9yaXplZCBjb3BpZXMuG1tLG1syMTs0
SBtbSxtbMjI7NEhUaGlzIGlzIGEgcmVnaXN0ZXJlZCB0cmFkZW1hcmsuG1tLDQo=
答案1
最好的办法是让终端模拟器解释这些序列,并告诉它转储结果中的文本部分。
screen
是您可以在脚本中轻松与之交互的终端模拟器之一。你可以这样做:
INPUT=file.txt OUTPUT=output.txt screen -Dmc /dev/null sh -c '
screen -X scrollback 100000
cat < "$INPUT"
screen -X hardcopy -h "$OUTPUT"'
这将使用空onfig 文件 ( ) 启动一个新的 ( -m
)蚀刻屏幕会话。在那里,我们在屏幕窗口中运行该内联脚本,增加回滚大小(尽管这里的输出适合一个屏幕),将输入文件转储到屏幕窗口中,然后调用转储屏幕内容,包括回滚到输出文件中。D
c
/dev/null
sh
hardcopy -h
答案2
该文件包含许多转义序列(字符序列^[
是转义字符):
^[[2J
,清除屏幕。^[[H
,将光标移动到屏幕顶部。^[[x;yH
,将光标移至位置(x,y)
。这意味着该文件基本上使用文本在屏幕上的位置的绝对定位。
^[[K
清除到行尾。
该文件还包含一些我们可能想要删除的回车符。
我们可以选择删除其中的大部分,但(x,y)
为了简单起见,用单个换行符替换“移动到”序列。幸运的是,每次这样的定位只是将光标向下移动一行,并将其缩进四个空格(不存在“不按顺序”的文本行)。
sed -e $'s/\e\\[2J//g' \
-e $'s/\e\\[H//g' \
-e $'s/\e\\[[[:digit:]]*;[[:digit:]]*H/@ /g' -e 'y/@/\n/' \
-e $'s/\e\\[K//g' \
-e $'s/\r//g' file
这里的替换是使用 shell 中的 C 字符串(由eg和$'...'
支持)来对转义字符进行编码。bash
zsh
每个^[[x;yH
序列都以两步方式替换为换行符和四个缩进空格;首先将它们替换为@
(@
是数据中不存在的任何字符),然后@
使用 将每个字符替换为换行符y///
。这是由于s///
无法插入换行符(尽管 GNUsed
可以)。
我们还可以选择使用cat -v
数据运行的输出。这使得一些控制字符以明确的方式可见。
$ cat -v file
^[[H^[[2J^[[1;1H^M
^[[4;4H CONFIDENTIAL INFORMATION^[[K^[[5;4H^[[K^[[6;4H^[[K^[[7;4HThis work contains valuable, confidential, and proprietary information.^[[K^[[8;4HDisclosure, use, or reproduction is governed by your License Agreement.^[[K^[[10;4H^[[K^[[11;4HThis unpublished work is protected by the laws of the United States and^[[K^[[12;4Hother Countries. The work was created in 1988 and revised in 1994. ^[[K^[[13;4HIf publication occurs, the following notice shall apply:^[[K^[[14;4H^[[K^[[15;4H^[[K^[[16;4H Copyright 1988,1994. All rights reserved.^[[K^[[17;4H^[[K^[[18;4H^[[K^[[19;4HThis Copyright notice and other copyright notices included in the machine^[[K^[[20;4Hreadable copies must be reproduced on all authorized copies.^[[K^[[21;4H^[[K^[[22;4HThis is a registered trademark.^[[K^M
在这里,我们可以使用以下sed
命令:
cat -v file |
sed -e 's/\^\[\[2J//g' \
-e 's/\^\[\[H//g' \
-e 's/\^\[\[[[:digit:]]*;[[:digit:]]*H/@ /g' -e 'y/@/\n/' \
-e 's/\^\[\[K//g' \
-e 's/\^M//g'
请注意,-v
选项cat
不是标准的,但支持它的实现的输出cat
似乎是一致的。
在某些系统上,该vis
实用程序可以用来代替cat -v
,但它会生成控制字符的其他可见表示。
答案3
使用带有删除选项的截断命令的简单方法。 \033 代表转义字符。
$cat your_filename|tr -d \033 > save_filename
使用以下命令删除所有控制字符
$cat your_filename|tr -d [:cntrl:] > save_filename
希望有帮助