【发布时间】:2010-11-24 21:42:40
【问题描述】:
我有一个文本文件 (.txt),它可以是制表符分隔格式或管道分隔格式,我需要将其转换为 CSV 文件格式。我正在使用python 2.6。谁能建议我如何识别文本文件中的分隔符,读取数据然后将其转换为逗号分隔的文件。
提前致谢
【问题讨论】:
-
要获得合理的答案,您需要指定作者如何引用或转义分隔符(如果有的话),以及如何引用或转义引号或转义字符本身(如果有的话) .
我有一个文本文件 (.txt),它可以是制表符分隔格式或管道分隔格式,我需要将其转换为 CSV 文件格式。我正在使用python 2.6。谁能建议我如何识别文本文件中的分隔符,读取数据然后将其转换为逗号分隔的文件。
提前致谢
【问题讨论】:
这样
from __future__ import with_statement
import csv
import re
with open( input, "r" ) as source:
with open( output, "wb" ) as destination:
writer= csv.writer( destination )
for line in input:
writer.writerow( re.split( '[\t|]', line ) )
【讨论】:
csv 处理。
for line in open("file"):
line=line.strip()
if "|" in line:
print ','.join(line.split("|"))
else:
print ','.join(line.split("\t"))
【讨论】:
line.strip('\n')。 -1 未提及引用/转义分隔符(和引号/转义字符)。
我担心你在不知道它是什么的情况下无法识别分隔符。 CSV 的问题在于,quoting ESR:
Microsoft 版本的 CSV 是如何不设计文本文件格式的教科书示例。
如果分隔符可以出现在字段中,则需要以某种方式进行转义。在不知道如何进行转义的情况下,自动识别它是很困难的。转义可以通过 UNIX 方式完成,使用反斜杠“\”,或者 Microsoft 方式,使用引号,然后也必须转义。这不是一项简单的任务。
所以我的建议是从生成您要转换的文件的人那里获取完整的文档。然后,您可以使用其他答案中建议的一种方法或一些变体。
编辑:
Python 提供了csv.Sniffer,可以帮助您推断出 DSV 的格式。如果您的输入看起来像这样(注意第二行第一个字段中的引号分隔符):
a|b|c
"a|b"|c|d
foo|"bar|baz"|qux
你可以这样做:
import csv
csvfile = open("csvfile.csv")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.DictReader(csvfile, dialect=dialect)
for row in reader:
print row,
# => {'a': 'a|b', 'c': 'd', 'b': 'c'} {'a': 'foo', 'c': 'qux', 'b': 'bar|baz'}
# write records using other dialect
【讨论】:
我建议从现有答案中获取一些示例代码,或者最好使用 python 中的csv 模块并将其更改为首先假定制表符分隔,然后管道分隔,并生成两个逗号分隔的输出文件.然后,您可以目视检查这两个文件以确定您想要哪个文件并选择它。
如果您实际上有很多文件,那么您需要尝试找到一种方法来检测哪个文件是哪个文件。
其中一个例子是这样的:
if "|" in line:
这可能就足够了:如果文件的第一行包含一个管道,那么可能整个文件是管道分隔的,否则假设一个制表符分隔的文件。
或者将文件修复为在第一行包含一个易于识别的关键字段 - 或者第一行可能包含可以检测到的列标题。
【讨论】:
您的策略可能如下:
在以下示例中,您会找到更简单的统计信息(字段总数)
import csv
piperows= []
tabrows = []
#parsing | delimiter
f = open("file", "rb")
readerpipe = csv.reader(f, delimiter = "|")
for row in readerpipe:
piperows.append(row)
f.close()
#parsing TAB delimiter
f = open("file", "rb")
readertab = csv.reader(f, delimiter = "\t")
for row in readerpipe:
tabrows.append(row)
f.close()
#in this example, we use the total number of fields as indicator (but it's not guaranteed to work! it depends by the nature of your data)
#count total fields
totfieldspipe = reduce (lambda x,y: x+ y, [len(f) for f in piperows])
totfieldstab = reduce (lambda x,y: x+ y, [len(f) for f in tabrows])
if totfieldspipe > totfieldstab:
yourrows = piperows
else:
yourrows = tabrows
#the var yourrows contains the rows, now just write them in any format you like
【讨论】: