如何使用Python 3查找/替换非可打印/非ASCII字符?

时间:2019-02-08 10:31:44

标签: python-3.x csv non-ascii-characters

我有一个文件,.csv文件中的某些行由于行中某些字段中的时髦字符而阻塞了数据库导入。

我已经搜索并找到了有关如何在Python 3中替换非ascii字符的文章,但是没有任何效果。

当我在vi中打开文件并执行:set列表时,在行末不应该有$,在下一行的开始有^ I ^ I。这两行应该是一条连接的行,并且那里没有^ I。我知道$是行'\ n'的结尾,并试图替换它们,但是没有任何效果。

我不知道^ I代表什么,可能是制表符。


我尝试使用此功能无济于事:

def remove_non_ascii(text):
    new_text = re.sub(r"[\n\t\r]", "", text)
    new_text = ''.join(new_text.split("\n"))
    new_text = ''.join([i if ord(i) < 128 else ' ' for i in new_text])
    new_text = "".join([x for x in new_text if ord(x) < 128])
    new_text = re.sub(r'[^\x00-\x7F]+', ' ', new_text)
    new_text = new_text.rstrip('\r\n')
    new_text = new_text.strip('\n')
    new_text = new_text.strip('\r')
    new_text = new_text.strip('\t')
    new_text = new_text.replace('\n', '')
    new_text = new_text.replace('\r', '')
    new_text = new_text.replace('\t', '')
    new_text = filter(lambda x: x in string.printable, new_text)
    new_text = "".join(list(new_text))

    return new_text

是否有一些工具可以准确地告诉我这个令人讨厌的角色是什么,然后找到替换它的方法?

我像这样打开文件(.csv已保存为UTF-8)

f_csv_in = open(csv_in, "r", encoding="utf-8")

下面两行应为一行,并且可见非ASCII字符问题。

这两行应该是一行。请注意,第37行的末尾是$,第38行以^ I ^ I开头。

vi显示的部分问题是,我不希望它出现在第37行上有新行$。这应该是一行。

37 Cancelled,01-19-17,,basket,00-00-00,00-00-00,,,,98533,SingleSource,,,17035 Cherry Hill Dr,"L/o 1-19-17 @ 11:45am$
38 ^I^IVictorville",SAN BERNARDINO,CA,92395,,,,,0,,,,,Lock:6111 ,,,No,No,,0.00,0.00,No,01-19-17,0.00,0.00,,01-19-17,00-00-00,,provider,,,Unread,00-00-00,,$

3 个答案:

答案 0 :(得分:0)

删除非ASCII字符的一种简单方法是:

new_text = "".join([c for c in text if c.isascii()])
  

注意:如果您要从文件中读取此文本,请确保以正确的编码读取

答案 1 :(得分:0)

对于不可打印字符,内置的字符串模块具有一些过滤掉不可打印或非ASCII字符的方式,例如。具有isprintable()功能。
下面介绍了一种一次性过滤整个字符串的简洁方法

>>> import string
>>>
>>> str1 = '\nsomestring'
>>> str1.isprintable()
False
>>> str2 = 'otherstring'
>>> str2.isprintable()
True
>>>
>>> res = filter(lambda x: x in string.printable, '\x01mystring')
>>> "".join(list(res))
'mystring'

这个问题过去在SO上有一些discussion,但是有很多处理方法,所以我知道这可能会造成混淆,因为您可以使用从正则表达式到str.translate()的任何内容

另一种方法是查看Unicode Categories,然后根据需要的符号集过滤出数据。

答案 2 :(得分:0)

似乎您的csv文件包含带引号的值,例如,嵌入式逗号或换行符之类的值必须用引号引起来,以便csv读取器正确处理它们。

如果查看示例数据,则可以看到第一行的末尾有一个双引号,但没有闭合的双引号,第二行的末尾有一个闭合的双引号,而没有任何双引号,表明引号包含一个带有嵌入式换行符。

将行分成两部分的事实可能是用于查看它们的应用程序的伪造品,或者是处理它们的代码:如果软件不理解csv引用,它将假定每个换行符表示一个新行

目前尚不清楚这会在数据库中引起什么问题,但是引号字符(尤其是不匹配的引号)很可能会引起问题,尤其是如果在插入之前未正确转义数据的情况下。

此代码段将重写文件,删除嵌入的逗号,换行符和制表符,并指示编写者不要引用任何值。如果找到需要转义的值,它将失败并显示错误消息_csv.Error: need to escape, but no escapechar set。根据您的数据,您可能需要调整正则表达式模式。

with open('lines.csv') as f, open('fixed.csv', 'w') as out:
    reader = csv.reader(f)
    writer = csv.writer(out, quoting=csv.QUOTE_NONE)
    for line in reader:
        new_row = [re.sub(r'\t|\n|,', ' ', x) for x in line]
        writer.writerow(new_row)
相关问题