如何使用Python删除扩展ASCII字符?

5

在尝试修复PML(Palm Markup Language)文件时,我的测试文件似乎有非ASCII字符,这导致MakeBook出现问题。解决方法是在PML中剥离所有的非ASCII字符。

因此,在Python中尝试修复这个问题,我已经:

import unicodedata, fileinput

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

然而,这会导致一个错误,即行必须是“unicode”,而不是“str”。下面是一个文件片段。
\B1a\B \tintense, disordered and often destructive rage†.†.†.\t

我不太确定在这一点上如何正确传递要处理的行。


你想过滤掉ASCII值大于255的任何字符吗? - Adam Matan
严格来说,扩展ASCII并不存在。ASCII定义了0到127之间的值。任何高于此范围的值只能被任意解释。也许你应该使用“非ASCII字符”这个术语。 - dreamlax
相关:终端输出的安全转义函数 http://stackoverflow.com/questions/437476/safe-escape-function-for-terminal-output - jfs
4个回答

5
尝试使用print line.decode('iso-8859-1').encode('ascii', 'ignore') -- 这应该更接近你想要的结果。

这似乎能够工作,尽管MakeBook现在正在抱怨非法控制代码。 - Jauder Ho
@Jauder,当然你也可以删除控制字符,例如在上面的clean=''.join(c for c in line if ord(c)>=32)之后(删除所有控制字符,包括换行符和回车符 - 根据需要进行调整,我们无法在不知道要删除哪些控制字符的情况下为您完成!)。 - Alex Martelli
@Alex,如果我知道的话,我就会这么做 =)。问题是我正在使用一个只发出加密错误消息的没有源代码的Java程序。http://gist.github.com/227882 - Jauder Ho
但理想情况下,我希望删除杂乱的控制码,但保留LF/CR。 - Jauder Ho
@Jauder,好的,但我不知道哪些是“虚假的”。那么怎么样:spurious=set(chr(c) for c in range(32))-set('\r\n\t'),当然还有 clean-''.join(c for c in line if c not in spurious,然后通过经验试验交互式地调整 spurious,直到它恰好是您需要删除的字符集。 - Alex Martelli

4
您想将line视为ASCII编码数据,因此答案是使用ascii编解码器将其解码为文本:

line.decode('ascii')

这会导致对实际上不是ASCII编码的数据引发错误。以下是如何忽略这些错误:

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

这将给您提供文本形式的unicode实例。如果您更愿意使用(ascii编码)数据而不是文本,则可以重新编码以获取strbytes实例(取决于您的Python版本):

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


2
要删除非ASCII字符,请使用line.decode(your_file_encoding).encode('ascii', 'ignore')。但是最好使用PLM转义序列来处理它们:
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)

这将输出\B1a\B \t强烈、混乱且常常具有破坏性的愤怒\U2020.\U2020.\U2020.\t

使用正则表达式删除非ASCII和控制字符也很容易(在转义后可以安全使用):

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

0

在Python中从文件读取时,你会得到字节字符串,也就是Python 2.x及更早版本中的“str”。你需要使用decode方法将它们转换为“unicode”类型。例如:

line = line.decode('latin1')

将'latin1'替换为正确的编码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接