Python 的 csv
模块是硬编码的(用 C 语言(,以便在使用阅读器时立即将回车/换行识别为行的末尾。
在许多情况下,我不得不编写一个脚本(在 Python 中,因为像 sed
这样的工具通常不处理换行符/回车符(,用未使用的文本字符(垂直制表符(逐字节替换单元格内换行符,然后在再次解析时用 csv 阅读器替换它。
我必须处理两种主要情况:
-
真正的"行尾"总是由
rn
表示,而单元格内换行符只是n
-
行尾都是
n
的,除了在引号字段中。(例如,val1,"first line of cellnsecond line of cell",val3
(
我正在处理的文件太大,无法在内存中有效处理,所以我想知道是否有替代解析器在遇到回车符或换行符后不会自动终止行。
csv
模块弄错了行尾 - 而是file
对象。csv 阅读器只是将其第一个参数视为迭代器。默认情况下,file
对象将所有样式的行尾视为行终止符。对于 Python 3,您可以通过打开带有参数的 csv 文件来解决您的问题 newline='rn'
:
reader = csv.DictReader(open('weird.csv', newline='rn'))
在 Python 2 中,您可以使用 io
模块:
import io
reader = csv.DictReader(io.open('weird.csv', newline='rn'))
请注意,这两种方法都依赖于正确引用包含换行符的字段。如果不是,您可以尝试使用引用包含换行符字段的生成器包装打开的文件(使用上述任一方法(,如下所示:
import re
def quote(fh, delimiter='t'):
for line in fh:
# using line.strip('rn') could improperly remove a
# leading or trailing n character
fields = re.sub('rn$', '', line).split(delimiter)
quoted = []
for field in fields:
if 'n' in field and not re.match('".*"$', field, re.MULTILINE):
# must quote any existing quotes!
field = '"{}"'.format(field.replace('"', '""')
quoted.append(field)
yield delimiter.join(quoted) + 'rn'
reader = csv.DictReader(quote(io.open('weird.csv', newline='rn')), delimiter='t')