2009-11-06 21 views
5

Próbując naprawić plik PML (Palm Markup Language), wygląda na to, że mój plik testowy zawiera znaki spoza zestawu ASCII, co powoduje składanie przez MakeBook skargi. Rozwiązaniem byłoby usunięcie wszystkich znaków spoza ASCII w PML.Jak usunąć rozszerzony ascii przy użyciu Pythona?

Więc próbując rozwiązać ten problem w Pythonie, mam

import unicodedata, fileinput 

for line in fileinput.input(): 
    print unicodedata.normalize('NFKD', line).encode('ascii','ignore') 

Powoduje to jednak w błędzie, że linia musi być „Unicode, nie STR”. Oto fragment pliku.

\B1a\B \tintense, disordered and often destructive rage†.†.†.\t 

Nie do końca wiem, jak poprawnie przekazać linię do przetworzenia w tym momencie.

+0

Czy chcesz odfiltrować dowolny znak ASCII, którego wartość jest większa niż 255? –

+0

Ściśle mówiąc, nie ma czegoś takiego jak Extended ASCII. ASCII definiuje wartości od 0 do 127. Wszystko powyżej może być interpretowane tylko arbitralnie. Być może powinieneś użyć terminu * znaki spoza ASCII *. – dreamlax

+0

Powiązane: Funkcja bezpiecznego wyjścia dla wyjścia terminalowego http://stackoverflow.com/questions/437476/safe-escape-function-for-terminal-output – jfs

Odpowiedz

0

Podczas odczytu z pliku w Pythonie otrzymujesz ciągi bajtów, zwane również "str" ​​w Pythonie 2.x i wcześniejszych. Konieczne jest przekonwertowanie ich na typ "Unicode" przy użyciu metody decode. np .:

line = line.decode('latin1') 

Zamień "latin1" na poprawne kodowanie.

5

Wypróbuj print line.decode('iso-8859-1').encode('ascii', 'ignore') - to powinno być znacznie bliższe temu, co chcesz.

+0

Wydaje się to działać, chociaż MakeBook narzeka teraz na nielegalne kody kontrolne. –

+0

@Jauder, możesz oczywiście również usunąć kody kontrolne, na przykład po powyższym 'clean = ''.join (c dla c w linii, jeśli ord (c)> = 32) '(usuwa WSZYSTKIE kody kontrolne, w tym znak nowej linii i powrót karetki - dostosuj się do smaku, nie możemy tego zrobić dla ciebie, nie wiedząc, CO ma kody kontrolne, które chcesz usunąć!-). –

+0

@Alex, gdybym wiedział, byłbym =). Problem polega na tym, że pracuję tylko z progamem Java bez dostępnego źródła, które emituje tylko tajemniczy komunikat o błędzie. http://gist.github.com/227882 –

5

Chcesz leczyć line jako dane ASCII kodowane, więc odpowiedź jest dekodować go do tekstu przy użyciu kodeka ASCII:

line.decode('ascii')

To podniesie błędów dla danych, które nie jest w rzeczywistości Kodowane ASCII. Oto, jak zignorować te błędy:

line.decode('ascii', 'ignore').

Daje to tekst w postaci instancji unicode. Jeśli wolisz pracować z (ASCII kodowane) danych, a nie tekst, można ponownie zakodować to, aby wrócić do str lub bytes instancji (w zależności od wersji Pythona):

line.decode('ascii', 'ignore').encode('ascii')

2

spadać znaki nie-ASCII używają line.decode(your_file_encoding).encode('ascii', 'ignore'). Ale chyba lepiej użyć sekwencje PLM dla nich:

import re 

def escape_unicode(m): 
    return '\\U%04x' % ord(m.group()) 

non_ascii = re.compile(u'[\x80-\uFFFF]', re.U) 

line = u'\\B1a\\B \\tintense, disordered and often destructive rage\u2020.\u2020.\u2020.\\t' 
print non_ascii.sub(escape_unicode, line) 

ten wyprowadza \B1a\B \tintense, disordered and often destructive rage\U2020.\U2020.\U2020.\t.

Dropping non-ASCII i kontroli znaków z wyrażenia regularnego jest zbyt łatwe (to może być bezpiecznie stosowany po ucieczce):

regexp = re.compile('[^\x09\x0A\x0D\x20-\x7F]') 
regexp.sub('', line) 
Powiązane problemy