簡體   English   中英

如何在 Bash (linux) 或 Python 上僅過濾文件中的可打印字符?

[英]How to filter only printable characters in a file on Bash (linux) or Python?

我想制作一個包含不可打印字符的文件,只包含可打印字符。 我認為這個問題與ACSCII control action 有關,但我找不到解決方案,也無法理解以下文件中.[16D (ASCII control action character??) 的含義。

輸入文件的十六進制:

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

當我cat編上文件bash ,我剛:“HELLO”。 我認為這是因為默認cat解釋了 ASCII 控制動作,兩個.[16D s。

為什么兩個.[16D字符串使cat FILE 只是為了打印“HELLO”?,以及...我怎樣才能使該文件僅包含可打印的字符,即“HELLO”?

\\x1b顯示.[16D中的點實際上是一個轉義字符\\x1b
Esc[ n D是用於刪除n字符的ANSI 轉義碼 所以Esc[16D告訴終端刪除 16 個字符,這解釋了cat輸出。

有多種方法可以從文件中刪除 ANSI 轉義碼,可以使用 Bash 命令(例如使用sed ,如 Anubhava 的回答)或 Python。

但是,在這種情況下,最好通過終端仿真器運行文件以解釋文件中的任何現有編輯控制序列,以便在應用這些編輯序列后獲得文件作者想要的結果。

在 Python 中這樣做的一種方法是使用pyte ,這是一個 Python 模塊,它實現了一個簡單的 VTXXX 兼容終端模擬器。 您可以使用pip輕松安裝它,這里是readthedocs上的文檔

這是一個簡單的演示程序,用於解釋問題中給出的數據。 它是為 Python 2 編寫的,但很容易適應 Python 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.|

對我來說,以下命令運行良好,使用開箱即用的strings

head /dev/random | strings -ws ''

詳細說明:

head /dev/random :不是很重要,只是創建一些帶有隨機字符的行,包括可能會使屏幕變大的非打印字符。

-w & -s strings選項:(部分輸出man strings

-w --include-all-whitespace 默認情況下,顯示的字符串中包含制表符和空格字符,但不包含其他空白字符,例如換行符和回車符。 -w 選項更改了這一點,以便所有空白字符都被視為字符串的一部分。

-s --output-separator 默認情況下,輸出字符串由換行符分隔。 此選項允許您提供要用作輸出記錄分隔符的任何字符串。 與 --include-all-whitespace 一起使用,其中字符串可能在內部包含換行符。

使用-w-s選項,通過strings管道傳輸的數據按strings -ws ''處理,因此strings -ws ''打印可打印字符的序列。

您可以嘗試使用此sed命令從文件中刪除所有不可打印的字符:

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

我想到的簡約解決方案是

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]

請參閱內置字符串模塊。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM