【问题标题】:How to convert tab separated, pipe separated to CSV file format in Python如何在 Python 中将制表符分隔、管道分隔转换为 CSV 文件格式
【发布时间】:2010-11-24 21:42:40
【问题描述】:

我有一个文本文件 (.txt),它可以是制表符分隔格式或管道分隔格式,我需要将其转换为 CSV 文件格式。我正在使用python 2.6。谁能建议我如何识别文本文件中的分隔符,读取数据然后将其转换为逗号分隔的文件。

提前致谢

【问题讨论】:

  • 要获得合理的答案,您需要指定作者如何引用或转义分隔符(如果有的话),以及如何引用或转义引号或转义字符本身(如果有的话) .

标签: python csv


【解决方案1】:

这样

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 引用/转义由 csv 处理。
  • 关于空白的“愚蠢的地方”:在用数十种语言编程 30 年后,PEP-8 的某些部分我只是不打算遵循。
【解决方案2】:
for line in open("file"):
    line=line.strip()
    if "|" in line:
        print ','.join(line.split("|"))
    else:
        print ','.join(line.split("\t"))

【讨论】:

  • -1 用于 split()。 -1 用于带();大概 strip() 旨在摆脱换行符;它会这样做加上它会删除所有其他尾随空格(包括制表符);请改用line.strip('\n')。 -1 未提及引用/转义分隔符(和引号/转义字符)。
【解决方案3】:

我担心你在不知道它是什么的情况下无法识别分隔符。 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

【讨论】:

  • 我不明白这个问题。源是制表符或管道。输出为 CSV。需要什么“完整文件”?
  • 如果选项卡或管道是字段内容的一部分会怎样?您必须知道如何转义分隔符才能处理此问题。仅仅在分隔符上分割线是不够的。
  • 这只读取文件。您将如何将其写回 CSV?
【解决方案4】:

我建议从现有答案中获取一些示例代码,或者最好使用 python 中的csv 模块并将其更改为首先假定制表符分隔,然后管道分隔,并生成两个逗号分隔的输出文件.然后,您可以目视检查这两个文件以确定您想要哪个文件并选择它。

如果您实际上有很多文件,那么您需要尝试找到一种方法来检测哪个文件是哪个文件。
其中一个例子是这样的:

if "|" in line:

这可能就足够了:如果文件的第一行包含一个管道,那么可能整个文件是管道分隔的,否则假设一个制表符分隔的文件。

或者将文件修复为在第一行包含一个易于识别的关键字段 - 或者第一行可能包含可以检测到的列标题。

【讨论】:

    【解决方案5】:

    您的策略可能如下:

    • 使用制表符分隔的 csv 阅读器和管道分隔的 csv 阅读器来解析文件
    • 计算结果行的一些统计数据以确定哪个结果集是您要写入的结果集。一个想法可能是计算两个记录集中的字段总数(期望选项卡和管道不那么常见)。另一种方法(如果您的数据结构很强,并且您希望每行中的字段数相同)可以测量每行字段数的标准差,并采用标准差最小的记录集。

    在以下示例中,您会找到更简单的统计信息(字段总数)

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      相关资源
      最近更新 更多