【问题标题】:How to filter only printable characters in a file on Bash (linux) or Python?如何仅过滤 Bash(linux)或 Python 文件中的可打印字符?
【发布时间】:2015-06-01 10:18:37
【问题描述】:

我想让一个包含不可打印字符的文件只包含可打印字符。我认为这个问题与ACSCII control action 有关,但我找不到解决方案,也无法理解以下文件中.[16D(ASCII 控制操作字符??)的含义。

输入文件的十六进制转储:

00000000: 4845 4c4c 4f20 5448 4953 2049 5320 5448 HELLO THIS IS TH
00000010: 4520 5445 5354 1b5b 3136 4420 2020 2020 E TEST.[16D
00000020: 2020 2020 2020 2020 2020 201b 5b31 3644            .[16D
00000030: 2020

当我在bashcated 那个文件时,我刚刚得到:“HELLO”。我认为这是因为默认 cat 解释了 ASCII 控制操作,两个 .[16Ds。

为什么两个.[16D 字符串会生成cat FILE 只是为了打印“HELLO”?以及...我怎样才能使该文件仅包含可打印字符,即“HELLO”?

【问题讨论】:

  • 你试过 string.printable 了吗?
  • 不知道为什么python标签....
  • 在大多数 *nix 系统上,当然在任何 GNU 系统上,都应该有一个strings 命令。
  • string.printable 不工作。在问这个之前我已经试过了。

标签: python linux bash ascii


【解决方案1】:

hexdump 显示.[16D 中的点实际上是一个转义字符,\x1b
Esc[nD 是一个ANSI escape code 以删除n人物。所以Esc[16D 告诉终端删除16 个字符,这就解释了cat 的输出。

有多种方法可以从文件中删除 ANSI 转义码,可以使用 Bash 命令(例如使用 sed,如 Anubhava 的回答)或 Python。

但是,在这种情况下,最好通过终端模拟器运行文件以解释文件中任何现有的编辑控制序列,这样您就可以获得文件作者在应用这些编辑序列后想要的结果。

在 Python 中执行此操作的一种方法是使用 pyte,这是一个 Python 模块,它实现了一个简单的 VTXXX 兼容终端仿真器。您可以使用pip 轻松安装它,这里是readthedocs 上的文档。

这是一个解释问题中给出的数据的简单演示程序。它是为 Python 2 编写的,但很容易适应 Python 3。pyte 支持 Unicode,它的标准 Stream 类需要 Unicode 字符串,但这个示例使用 ByteStream,所以我可以将它传递给纯字节字符串。

#!/usr/bin/env python

''' pyte VTxxx terminal emulator demo

    Interpret a byte string containing text and ANSI / VTxxx control sequences

    Code adapted from the demo script in the pyte tutorial at
    http://pyte.readthedocs.org/en/latest/tutorial.html#tutorial

    Posted to http://stackoverflow.com/a/30571342/4014959 

    Written by PM 2Ring 2015.06.02
'''

import pyte


#hex dump of data
#00000000  48 45 4c 4c 4f 20 54 48  49 53 20 49 53 20 54 48  |HELLO THIS IS TH|
#00000010  45 20 54 45 53 54 1b 5b  31 36 44 20 20 20 20 20  |E TEST.[16D     |
#00000020  20 20 20 20 20 20 20 20  20 20 20 1b 5b 31 36 44  |           .[16D|
#00000030  20 20                                             |  |

data = 'HELLO THIS IS THE TEST\x1b[16D                \x1b[16D  '

#Create a default sized screen that tracks changed lines
screen = pyte.DiffScreen(80, 24)
screen.dirty.clear()
stream = pyte.ByteStream()
stream.attach(screen)
stream.feed(data)

#Get index of last line containing text
last = max(screen.dirty)

#Gather lines, stripping trailing whitespace
lines = [screen.display[i].rstrip() for i in range(last + 1)]

print '\n'.join(lines)

输出

HELLO

输出的十六进制转储

00000000  48 45 4c 4c 4f 0a                                 |HELLO.|

【讨论】:

  • 感谢您的标签。但是 cat FILE 到另一个文件只是 FILE 的副本,其中还包括不可打印的字符。我已经试过了...你有其他解决方案吗?...
  • 对不起@freddy。我应该意识到cat 不会真的 清理那些控制序列。我目前正在尝试找到可以完成这项工作的一些东西,但我今晚可能找不到解决方案。
  • @freddy:FWIW,简单地摆脱像ESC[nD 这样的任何ANSI 序列并不太难,在你的OP 中的例子中会给你HELLO THIS IS THE TEST。你想要那个,还是想要简单的HELLO
  • @freddy:我添加了一些代码,展示了如何使用 PYthon 终端仿真器 pyte 来解释包含 ANSI 控制序列的文本。
【解决方案2】:

对我来说,以下命令运行良好,使用开箱即用的strings

head /dev/random | strings -ws ''

详细解释:

head /dev/random : 不太重要,只是创建一些带有随机字符的行,包括非打印字符,这可能会使你的屏幕变大。

-w & -s strings 的选项:(man strings 的部分输出)

-w --include-all-whitespace 默认情况下,显示的字符串中包含制表符和空格字符,但不包含其他空白字符,例如换行符和回车符。 -w 选项对此进行了更改,以便所有空白字符都被视为字符串的一部分。

-s --输出分隔符 默认情况下,输出字符串由换行符分隔。此选项允许您提供要用作输出记录分隔符的任何字符串。与 --include-all-whitespace 一起使用,其中字符串可能在内部包含换行符。

使用-w-s 选项,通过strings 管道传输的数据按原样处理,因此strings -ws '' 打印可打印字符的序列。

【讨论】:

    【解决方案3】:

    您可以尝试使用此sed 命令从文件中删除所有不可打印的字符:

    sed -i.bak 's/[^[:print:]]//g' file
    

    【讨论】:

    • 这是正确的,但要注意什么是可打印的,什么是不可打印的取决于区域设置。
    【解决方案4】:

    我想到的简约解决方案是

    import string
    printable_string = filter(lambda x: x in string.printable, your_string)
    ## TODO: substitute your string in the place of "your_string"
    

    如果这仍然没有帮助,那么尝试也包括 uni-code 特定 [curses.ascii]

    【讨论】:

      【解决方案5】:

      查看内置的string 模块。

      import string
      printable_str = filter(string.printable, string)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多