在带引号的CSV文件中匹配未转义的引号

6

我看了几篇标题类似的Stack Overflow帖子,但是没有一个被接受的答案对我有用。

我有一个CSV文件,其中每个数据“单元”由逗号分隔并带引号(包括数字)。每行以换行符结束。

一些文本“单元”中有引号,我想使用正则表达式找到它们,以便我可以正确地转义它们。

示例行:

"0","0.23432","234.232342","data here dsfsd hfsdf","3/1/2016",,"etc","E 60"","AD"8"\n

我希望匹配E 60AD"8中的",但不包括其他的"。请问有什么(最好是适用于Python的)正则表达式可以实现此功能?

https://regex101.com/r/VxEXf2/3 - 0m3r
1
谢谢回复!这很接近,但是我想匹配那些内部引号字符,以便我可以替换它们(例如,我不想替换E 60部分)。我认为我还需要将其他字符串的其余部分变得更加灵活,而不是限制在单个数字和字母中(请参见更新后的原始帖子示例)。 - sundance
你能同时更新你想要的匹配吗? - 0m3r
匹配是相同的 - 只是内部的 " 字符不同。我认为这样做可以,虽然可能不够高效:r'(?<!^)(?<!,)\"(?!,|$)' - sundance
https://regex101.com/r/qbPgxJ/1 - 0m3r
2个回答

3

编辑:更新了@sundance的正则表达式,以避免行首和换行符。

您可以尝试替换仅不在逗号、行首或换行符旁边的引号:

import re

newline = re.sub(r'(?<!^)(?<!,)"(?!,|$)', '', line)

成功了!我先使用re.compile进行编译,然后在编译后的正则表达式字符串上使用sub方法。大约用了3-4分钟就清理了我的400万行文件。 - sundance

1

不使用正则表达式,而是使用Python的字符串函数来查找并转义字符串中左右最外层引号之间的引号。它使用字符串的.find().rfind()方法来查找包围的"字符。然后对任何出现在外部引号内的额外"字符进行替换。这样做不会假设用,分隔符分隔的包围引号的位置,因此它将保留任何周围的空格不变(例如,它会将每行末尾的'\n'保持原样)。

def escape_internal_quotes(item):
    left = item.find('"') + 1
    right = item.rfind('"')
    if left < right:
        # only do the substitution if two surrounding quotes are found
        item = item[:left] + item[left:right].replace('"', '\\"') + item[right:]
    return item

line = '"0","0.23432","234.232342","data here dsfsd hfsdf","3/1/2016",,"etc","E 60"","AD"8"\n'
escaped = [escape_internal_quotes(item) for item in line.split(',')]
print(repr(','.join(escaped)))

导致:

结果为:

'"0","0.23432","234.232342","data here dsfsd hfsdf","3/1/2016",,"etc","E 60\\"","AD\\"8"\n'

这种方法可能会得到相同的答案,但肯定比正则表达式引擎效率低。我需要在400万行上执行此操作,因此性能将是一个问题。 - sundance
@sundance 感谢您的反馈。我没有意识到您的文件有多大。我运行了计时器,并发现非正则表达式解决方案需要大约两倍的时间(因此对于您的文件大约需要8分钟)。 - Craig

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