从文本文件中删除非打印的“gremlin”字符

10

我正在使用Python处理大量CSV文件,这些文件来自外部组织,并且采用多种编码方式进行编码。我希望找到自动化方法来删除以下内容:

  • 非ASCII字符
  • 控制字符
  • 空(ASCII 0)字符

我有一个名为“查找和替换”的产品,可以使用正则表达式,因此使用正则表达式解决上述问题的方法将非常有帮助。

谢谢


这些文件来自外部组织,使用各种编码进行编码 - 那些是...请他们不要这样做?你的相关产品与此有什么关系?你想用这些数据做什么...你真的需要Python吗? - Jon Clements
好问题。CSV文件。编码包括“unknown”(根据Find and Replace It!),'utf-8','iso-88591-1'和其他编码。不能问他们 - 邮件太多,太长了。我已经编写了重格式化CSV文件的Python脚本。在大多数情况下,脚本都能正常工作,除非有些小错误(类似于\r)破坏了CSV.reader。删除非ASCII编码的字符就可以解决问题。谢谢! - John Steedman
感谢所有这些评论。在赶工作时,我使用了一个被称为BBEdit的东西,它可以删除“小精灵”,例如使用Python无法识别的编码进行编码的/r字符(如果不进一步处理)。现在我知道如何使用BBEdit识别这些小精灵后,我将检查下面的解决方案中是否有任何执行相同操作的,并勾选第一个这样做的答案。 - John Steedman
4个回答

9
你可能会对以下替代方案感兴趣:
import string
clean = lambda dirty: ''.join(filter(string.printable.__contains__, dirty))

它只是从接收到的脏字符串中过滤掉所有的非打印字符。
>>> len(clean(map(chr, range(0x110000))))
100

6

试试这个:

clean = re.sub('[\0\200-\377]', '', dirty)

这个想法是匹配每个NUL或“高ASCII”字符(即\0和那些不符合7位的字符),并将它们删除。如果您发现更多的字符,例如ASCII ESC或BEL,可以添加它们。

或者这个:

clean = re.sub('[^\040-\176]', '', dirty)

这个想法是只允许“可打印ASCII”范围内的字符,但请注意这也会移除换行符。如果你想保留换行符、制表符或类似的内容,只需将它们添加到方括号中。


谢谢。我会尝试今天回来。我不需要保留选项卡,但我需要保留换行符(并希望在CSV封闭内部保留有效的CR),无论如何编码。 - John Steedman

3

用空格(删除它)替换任何不是所需字符的内容:

clean = re.sub('[^\s!-~]', '', dirty)

这允许所有空格(空格,换行符,制表符等),以及所有“正常”的字符(是第一个可打印的ASCII字符,~是小于128的最后一个可打印的ASCII字符)。

1

由于此内容出现在Google上,我们不再针对Python 2.x进行目标设定,我应该提及字符串中的isprintable方法。

它并不完美,因为它将空格视为可打印字符,但将换行符和制表符视为不可打印,但我可能会这样做:

whitespace_normalizer = re.compile('\s+', re.UNICODE)
cleaner = lambda instr: ''.join(x for x in whitespace_normalizer.sub(' ', instr) if x.isprintable())

正则表达式执行类似HTML的空格折叠(即将根据Unicode定义的任意空格范围转换为单个空格),然后lambda函数除去任何被Unicode分类为“分隔符”或“其他”的非空格字符。
然后您会得到以下结果:
>>> cleaner('foo\0bar\rbaz\nquux\tspam eggs')
'foobar baz quux spam eggs'

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