2015-06-01 15 views
5

Desidero creare un file che includa caratteri non stampabili per includere solo caratteri stampabili. Penso che questo problema sia relativo a ACSCII control action, ma non sono riuscito a trovare una soluzione per farlo e non potevo capire il significato di .[16D (carattere di controllo ASCII ??) nel seguente file.Come filtrare solo i caratteri stampabili in un file su Bash (linux) o Python?

Hexdump DI INGRESSO FILE:

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 

Quando ho cat ndr che il file sul bash, ho appena ricevuto: "CIAO". Penso che questo sia dovuto al fatto che il valore predefinito cat interpreta quell'azione di controllo ASCII, due .[16D s.

Perché due stringhe .[16D fanno cat FILE solo per stampare "CIAO"? E ... come posso creare quel file solo per includere caratteri stampabili, ad esempio "CIAO"?

+0

hai provato string.printable? – therealprashant

+0

Mi chiedo perché il tag python .... – 0xc0de

+0

Sulla maggior parte dei sistemi * nix, e certamente su qualsiasi sistema GNU, dovrebbe esserci un comando [stringhe] (http://linux.die.net/man/1/strings) . –

risposta

2

La hexdump mostra che il punto in .[16D è in realtà un carattere di escape, \x1b.
Esc[nD è un ANSI escape code per eliminare n caratteri. Quindi, Esc[16D indica al terminale di eliminare 16 caratteri, il che spiega l'output di cat.

Esistono vari modi per rimuovere i codici di escape ANSI da un file, utilizzando i comandi di Bash (ad esempio utilizzando sed, come nella risposta di Anubhava) o Python.

Tuttavia, in casi come questo, potrebbe essere preferibile eseguire il file tramite un emulatore di terminale per interpretare eventuali sequenze di controllo di modifica esistenti nel file, in modo da ottenere il risultato desiderato dall'autore del file dopo aver applicato tali sequenze di modifica.

Un modo per farlo in Python è utilizzare pyte, un modulo Python che implementa un semplice emulatore di terminale VTXXX compatibile. Puoi installarlo facilmente usando pip, e qui ci sono i suoi documenti su readthedocs.

Ecco un semplice programma dimostrativo che interpreta i dati forniti nella domanda. È scritto per Python 2, ma è facile adattarsi a Python 3. pyte è compatibile con Unicode e la sua classe Stream standard prevede le stringhe Unicode, ma in questo esempio viene utilizzato un ByteStream, quindi posso passarlo una stringa di byte semplice.

#!/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) 

uscita

HELLO 

esadecimale discarica di uscita

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

Grazie per il tag. Ma cat FILE in un altro file era solo una copia di FILE che include anche caratteri non stampabili. L'ho già provato ... Hai un'altra soluzione? .. – freddy

+0

Mi dispiace @freddy. Avrei dovuto rendermi conto che 'cat' non farà _really_ ripulire quelle sequenze di controllo. Attualmente sto cercando di trovare _qualcosa_ che possa fare quel lavoro, ma questa sera non trovo la soluzione. –

+0

@freddy: FWIW, semplicemente sbarazzandosi di qualsiasi sequenza ANSI come 'ESC [nD' non è troppo difficile, che nell'esempio nel tuo OP ti darà" CIAO, QUESTO È IL TEST ". Lo vuoi, o vuoi il semplice 'CIAO'? –

1

Si può provare questo comando sed per rimuovere tutti i caratteri non stampabili da un file:

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

Questo è corretto, ma fai attenzione che ciò che è stampabile e ciò che non lo è dipende dalle impostazioni locali. – lcd047

+0

Sì, è corretto dipende dalle impostazioni locali. – anubhava

0

soluzione minimalista mi viene in mente è

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

Se ancora questo non aiuta quindi provare anche incluso uni-codice specifico [curses.ascii]

0

vedere il modulo integrato string.

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