如何清理linux'script'命令的输出


35

我正在使用linux'script'命令 http://www.linuxcommand.org/man_pages/script1.html来跟踪一些交互式会话。该文件的输出文件包含不可打印的字符,包括我的退格键。

有没有办法整理这些输出文件,使它们仅包含屏幕上显示的内容?

还是有另一种方式来记录交互式Shell会话(输入和输出)?


“或者还有另一种方式来记录交互式shell会话(输入和输出)?” 您知道asciinema.org吗?
masterxilo

Answers:


34

如果要查看文件,则可以通过输出发送输出col -bp。这解释了控制字符。然后,您可以根据需要减少传输量。

col -bp typescript | less -R

在某些系统上col不接受文件名参数,请改用以下语法:

col -bp <typescript | less -R

1
在我的系统上,col不接受文件名,所以我做了col -bp < typescript ,得到了我想要的。
安德鲁(Andrew)

对我不起作用,对一些输出进行加扰。
亚历克斯

1
在我的系统上less -R,本身提供的输出要比col -bp先行传递更好。
布莱恩·霍金斯

@BrianHawkins我同意。使用col -bp <typescript | less -R不会显示彩色控制台。使用less -R typescript会显示彩色控制台!
特雷弗·博伊德·史密斯

仅当您要在中以交互方式查看脚本时,这才有用less
Trevor Boyd Smith,

18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

这是输入到的字符串的一些解释perl

  • s/pattern//g表示对整个g输入字符串进行替换(该选项表示对整个字符串进行替换,而不是对第一个替换项停止)

这是对正则表达式模式的一些解释:

  • \e 匹配特殊的“转义”控制字符(ASCII 0x1A)
  • (并且)是一个小组的开始和结束
  • |表示该组可以匹配N个模式之一。N个模式在哪里
    • [^\[\]] 要么
    • \[.*?[a-zA-Z] 要么
    • \].*?\a
  • [^\[\]] 手段
    • 匹配一组非字符,其中非字符为[]
  • \[.*?[a-zA-Z] 手段
    • 匹配以开头的字符串,[然后进行非贪婪.*?直到第一个字母字符
  • \].*?\a 手段
    • 匹配以开头的字符串,]然后进行非贪婪操作,.*?直到您击中称为“警报(响铃)字符”的特殊控制字符为止

1
我仍然需要弄清楚怎么做,但这确实有效;)
asdmin

@asdmin-基本上,这会将的输出回显typescript到一个perl程序,该程序从输出中删除某些控制字符,然后将输出通过管道传输到unix col命令,该命令的-b选项将删除脚本中的所有“删除”关键工件。然后,它将输出通过管道传输到文本文件。
彼得诺尔

这对我来说是打字稿第一行中的输出,但这是最好的答案。
亚历克斯

这对于某些打字稿似乎效果很好。它肯定比接受的答案产生的输出更具可读性。
法扎德

传奇的答案!
zack

2

对于大量的script输出,我会迭代地一起破解一个perl脚本。否则,请使用出色的编辑器进行手动编辑。

现有的自动化方法不太可能以script某种方式重现某些重要时刻(例如,主机在等待某些用户输入的第一个字符时)在屏幕上显示的内容,从而从输出中删除控制字符。

例如,除了Andrew $,屏幕可能是空白的,如果您随后键入rm /*并按了12次退格键(远远超过了所需的次数),则最后显示在屏幕上的内容取决于正在运行的Shell,当前stty设置(您可能会在整个会话过程中进行更改)以及其他一些因素。

以上适用于连续捕获输入和输出的任何自动化方法。主要的替代方法是在会话期间的适当时间拍摄“屏幕快照”或剪切和粘贴屏幕(这是我为用户指南所做的操作,为日间日志做的记录等)。



2

我用cat filename它删除控制字符:-)


imo这是一个更好的答案,因为它实际上删除了所有控制字符。
Nathanael Farley 2014年

在OSX上,猫不会删除颜色控制字符...
尼克

9
实际上,cat根本不会删除控制字符,而是逐字输出它们,然后终端会对其进行解释。如果您的打字稿相对于终端缓冲区而言较短,并且您可以从终端进行复制和粘贴,那么这可能对您有用。如果您的打字稿很大,那就不好了。
mc0e

1
同意 这不会删除任何内容。它只是允许shell解释它们。它们仍然存在。
Kentgrav '17

2

如果您要记录的是命令(例如,稍后将其转换为bash脚本),则可以运行script(1),然后在其中运行

bash -x

之后grep,输出文件(通常为“ typescript”)查找以“ +”开头的行。正则表达式^\+可以解决问题。


2

如果要将输出写入文件:

col -bp < typescript >>newfile

如果需要,可以使用unix2dos命令将文件转换为Windows格式


1
在Ubuntu 14.04上,这会在行的开头和结尾留下很多垃圾。相当可读,但不是很干净。
mc0e

2

col -bp根据需要处理退格键(AFAIK)。但是它破坏了颜色逃逸序列。如果可能的话,最好先删除颜色序列,然后再处理退格键。

这是一个非常普遍的需求,我很惊讶没有更多的解决方案。编写会话脚本非常普遍,然后有人需要查看该过程。您希望消除所有小的键入错误,并使用颜色转义序列来创建该过程的“干净”脚本,以备将来参考。首选简单ASCII文本。我认为这是“人类可读”的目的,这是非常合理的事情。


1

我发现,如果您处于Perl可用的环境中,那么dewtall提供给Unix板上类似问题的答案可以更有效地从脚本输出中删除控制字符。

dewtall的脚本:

#!/usr/bin/perl
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \r | # Remove extra carriage returns also
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
       1 while s/[^\b][\b]//g;  # remove all non-backspace followed by backspace
    print;
}

删除控制字符:

./dewtalls-script.pl < output-from-script-that-needs-control-characters-removed


0

我找到了一个很好的方法。在我的系统上,长的输出行上撒有“ ^ M”(空格后跟回车符)。可以用空字符“ ^ @”很好地替换“ ^ M”,当您对文件进行分类时,它根本不会显示。

我也捕获时间,因此为了完美地重放文件,我不能简单地使用下面的命令完全删除“ ^ M”(因为scriptreplay计算字节):

tr '\r' '\0' | sed 's/ \x0//g'

我这样运行我的脚本命令:

script -t -f session.log 2>timing

因此,我之后要做的是:

cat session.log | tr '\r' '\0' > typescript 
scriptreplay -t timing | sed 's/ \x0//g'

第一次编辑(重播之前)保留文件中的字节数。第二个编辑(在重播之后)在随机的地方消除了空白。(请注意,默认情况下scriptreplay会查找名为“ typescript”的输入文件,这就是为什么我在“ timing”之后没有提供输入文件的原因。)


-1

输出上的dos2unix也可以解决问题


7
您能解释一下如何使用它来完成任务吗?
本N

-1

另一种解决方案是使用strings仅打印文件(或标准输入)中的可打印字符的解决方案:

strings -n 1 filename

-n 1选项将要保留的序列的最小长度设置为1,从而确保即使保留了由不可打印字符包围的单个可打印字符。

这种方法的一个缺点是,strings在可打印字符的相邻字符串之间添加了换行符。例如包含内容的文件

Foo<SOMECONTROLCHAR>Bar

(其中<SOMECONTROLCHAR>控制字符或其他任何不可打印的字符)将返回为

Foo
Bar

评论中提出的另一个问题是,控制字符的某些序列由可打印字符和不可打印字符的组合组成,这种方法只会删除其中的一部分。

但是,strings在删除问题中提到的退格等控制字符方面做得很好。


strings不会删除所有不可打印的字符。它标识并打印可打印字符的序列。那不是同一回事。
CVn

@MichaelKjörling,您是对的,默认情况下,strings仅打印最小长度为4的序列。我已通过添加-n 1将最小长度设置为1 的选项来更正我的答案。感谢您指出这一点。
justfortherec '16

答案仍然与strings删除所有不可打印的字符相同,因此以与编辑前相同的方式仍然是错误的。由于“某些颜色代码”(通常是控制代码)通常由可打印字符和不可打印字符组成,因此它显然也被破坏了。例如,一个控制码序列对改变的文本颜色可以是ESC[01;52m其中ESC是单转义字符(字节值27)。strings如您建议的那样使用将保留[01;52m在输出中,这毫无意义。
CVn

好点,@MichaelKjörling。特别是带有颜色代码的示例非常不幸。感谢您帮助我改善答案。修改是否可以适当解决您的问题?strings可能无法与其他答案做同样的工作,但恕我直言,这是解决问题中所述问题的有效方法。
justfortherec '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.