如何仅过滤 Bash(linux)或 Python 文件中的可打印字符?
How to filter only printable characters in a file on Bash (linux) or Python?
我想制作一个包含不可打印字符的文件,使其只包含可打印字符。我认为这个问题与 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
当我在 bash
上 cat
编辑该文件时,我刚得到:"HELLO "。我认为这是因为默认 cat
解释了 ASCII 控制操作,两个 .[16D
。
为什么两个 .[16D
字符串生成 cat
FILE 只是为了打印 "HELLO"?,以及...我怎样才能使该文件只包含可打印字符,即 "HELLO "?
您可以尝试使用此 sed
命令从文件中删除所有不可打印的字符:
sed -i.bak 's/[^[:print:]]//g' file
hexdump 显示 .[16D
中的点实际上是一个转义字符,\x1b
.
Esc[
nD
是一个ANSI escape code删除n
个字符。所以 Esc[16D
告诉终端删除 16 个字符,这解释了 cat
输出。
有多种方法可以从文件中删除 ANSI 转义码,使用 Bash 命令(例如使用 sed
,如 Anubhava 的回答)或 Python.
但是,在这种情况下,最好通过终端仿真器 运行 文件来解释文件中任何现有的编辑控制序列,这样您就可以得到文件作者想要的结果应用了那些编辑序列。
在 Python 中执行此操作的一种方法是使用 pyte, a Python module that implements a simple VTXXX compatible terminal emulator. You can easily install it using pip
, and here are its docs on readthedocs.
这是一个简单的演示程序,可以解释问题中给出的数据。它是为 Python 2 编写的,但很容易适应 Python 3。pyte
是 Unicode 感知的,它的标准 Stream class 需要 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
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.|
我想到的简约解决方案是
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]
查看内置 string 模块。
import string
printable_str = filter(string.printable, string)
对我来说,下面的命令效果很好,使用 strings
开箱即用
head /dev/random | strings -ws ''
详细说明:
head /dev/random
: 不太重要,只是创建一些包含随机字符的行,包括可能会占用屏幕的非打印字符。
-w
& -s
strings
的选项:(man strings
的部分输出)
-w
--include-all-whitespace
By default tab and space characters are included in the strings that are displayed, but other whitespace characters, such a newlines and carriage returns, are not. The -w option changes this so that all whitespace characters are considered to be part of a string.
-s
--output-separator
By default, output strings are delimited by a new-line. This option allows you to supply any string to be used as the output record separator. Useful with --include-all-whitespace where strings may contain new-lines internally.
使用 -w
和 -s
选项,通过 strings
传输的数据按原样处理,因此 strings -ws ''
打印可打印字符的序列。
我想制作一个包含不可打印字符的文件,使其只包含可打印字符。我认为这个问题与 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
当我在 bash
上 cat
编辑该文件时,我刚得到:"HELLO "。我认为这是因为默认 cat
解释了 ASCII 控制操作,两个 .[16D
。
为什么两个 .[16D
字符串生成 cat
FILE 只是为了打印 "HELLO"?,以及...我怎样才能使该文件只包含可打印字符,即 "HELLO "?
您可以尝试使用此 sed
命令从文件中删除所有不可打印的字符:
sed -i.bak 's/[^[:print:]]//g' file
hexdump 显示 .[16D
中的点实际上是一个转义字符,\x1b
.
Esc[
nD
是一个ANSI escape code删除n
个字符。所以 Esc[16D
告诉终端删除 16 个字符,这解释了 cat
输出。
有多种方法可以从文件中删除 ANSI 转义码,使用 Bash 命令(例如使用 sed
,如 Anubhava 的回答)或 Python.
但是,在这种情况下,最好通过终端仿真器 运行 文件来解释文件中任何现有的编辑控制序列,这样您就可以得到文件作者想要的结果应用了那些编辑序列。
在 Python 中执行此操作的一种方法是使用 pyte, a Python module that implements a simple VTXXX compatible terminal emulator. You can easily install it using pip
, and here are its docs on readthedocs.
这是一个简单的演示程序,可以解释问题中给出的数据。它是为 Python 2 编写的,但很容易适应 Python 3。pyte
是 Unicode 感知的,它的标准 Stream class 需要 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
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.|
我想到的简约解决方案是
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]
查看内置 string 模块。
import string
printable_str = filter(string.printable, string)
对我来说,下面的命令效果很好,使用 strings
开箱即用
head /dev/random | strings -ws ''
详细说明:
head /dev/random
: 不太重要,只是创建一些包含随机字符的行,包括可能会占用屏幕的非打印字符。
-w
& -s
strings
的选项:(man strings
的部分输出)
-w --include-all-whitespace By default tab and space characters are included in the strings that are displayed, but other whitespace characters, such a newlines and carriage returns, are not. The -w option changes this so that all whitespace characters are considered to be part of a string.
-s --output-separator By default, output strings are delimited by a new-line. This option allows you to supply any string to be used as the output record separator. Useful with --include-all-whitespace where strings may contain new-lines internally.
使用 -w
和 -s
选项,通过 strings
传输的数据按原样处理,因此 strings -ws ''
打印可打印字符的序列。