【问题标题】:Text File Parsing with Python使用 Python 解析文本文件
【发布时间】:2024-04-23 06:15:02
【问题描述】:

我正在尝试解析一系列文本文件并使用 Python (2.7.3) 将它们保存为 CSV 文件。所有文本文件都有一个 4 行长的标题,需要去掉。数据行有各种分隔符,包括“(引号)、-(破折号)、: 列和空格。我发现在 C++ 中使用所有这些不同的分隔符对其进行编码很痛苦,所以我决定在 Python 中尝试一下与 C/C++ 相比,做起来相对容易。

我编写了一段代码来测试它是否适用于单行数据并且它可以工作,但是我无法让它适用于实际文件。为了解析单行,我使用了文本对象和“替换”方法。看起来我当前的实现将文本文件作为列表读取,并且列表对象没有替换方法。

作为 Python 新手,我被困在了这一点上。任何意见将不胜感激!

谢谢!

# function for parsing the data
def data_parser(text, dic):
for i, j in dic.iteritems():
    text = text.replace(i,j)
return text

# open input/output files

inputfile = open('test.dat')
outputfile = open('test.csv', 'w')

my_text = inputfile.readlines()[4:] #reads to whole text file, skipping first 4 lines


# sample text string, just for demonstration to let you know how the data looks like
# my_text = '"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636'

# dictionary definition 0-, 1- etc. are there to parse the date block delimited with dashes, and make sure the negative numbers are not effected
reps = {'"NAN"':'NAN', '"':'', '0-':'0,','1-':'1,','2-':'2,','3-':'3,','4-':'4,','5-':'5,','6-':'6,','7-':'7,','8-':'8,','9-':'9,', ' ':',', ':':',' }

txt = data_parser(my_text, reps)
outputfile.writelines(txt)

inputfile.close()
outputfile.close()

【问题讨论】:

  • 你应该附上一份你需要解析的文件和预期的输出,这样会更容易帮助你。

标签: python parsing text file-io python-2.7


【解决方案1】:

我会使用for 循环来遍历文本文件中的行:

for line in my_text:
    outputfile.writelines(data_parser(line, reps))

如果您想逐行读取文件而不是在脚本开头加载整个内容,您可以执行以下操作:

inputfile = open('test.dat')
outputfile = open('test.csv', 'w')

# sample text string, just for demonstration to let you know how the data looks like
# my_text = '"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636'

# dictionary definition 0-, 1- etc. are there to parse the date block delimited with dashes, and make sure the negative numbers are not effected
reps = {'"NAN"':'NAN', '"':'', '0-':'0,','1-':'1,','2-':'2,','3-':'3,','4-':'4,','5-':'5,','6-':'6,','7-':'7,','8-':'8,','9-':'9,', ' ':',', ':':',' }

for i in range(4): inputfile.next() # skip first four lines
for line in inputfile:
    outputfile.writelines(data_parser(line, reps))

inputfile.close()
outputfile.close()

【讨论】:

  • 谢谢!那么跳过前 4 行的最佳方法是什么?承认,我找不到办法做到这一点,这就是我决定阅读整本书的原因。我应该将除前 4 行之外的文件写入另一个文件以运行上面的循环吗?我打赌应该有一个更简单的方法。编辑:哦,等等,我想你的意思是用上面的循环替换 txt = data_parser(my_text, reps) 行。
  • 如果您希望逐行读取文件而不是将整个内容加载到 ram脚本我可以更新我的答案。
  • 对不起,我一开始就弄错了(见我上面的编辑),但是谢谢,它工作得很好!!!现在,我很高兴了解“读行-解析-写行(逐行)”的做事方式。我有一些文件大小为 +500MB 的大文件,这可能会搞砸事情。你能用第二个例子更新你的答案吗?
  • 我用一次读取输入文件一行的版本更新了我的答案。
  • 非常感谢,谢谢! for i in range(4): inputfile.next() 是我在决定顺便阅读全文之前一直在寻找的东西!
【解决方案2】:

从接受的答案看来,您想要的行为是转身

skip 0
skip 1
skip 2
skip 3
"2012-06-23 03:09:13.23",4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,"NAN",-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636

进入

2012,06,23,03,09,13.23,4323584,-1.911224,-0.4657288,-0.1166382,-0.24823,0.256485,NAN,-0.3489428,-0.130449,-0.2440527,-0.2942413,0.04944348,0.4337797,-1.105218,-1.201882,-0.5962594,-0.586636

如果那是对的,那么我认为是这样的

import csv

with open("test.dat", "rb") as infile, open("test.csv", "wb") as outfile:
    reader = csv.reader(infile)
    writer = csv.writer(outfile, quoting=False)
    for i, line in enumerate(reader):
        if i < 4: continue
        date = line[0].split()
        day = date[0].split('-')
        time = date[1].split(':')
        newline = day + time + line[1:]
        writer.writerow(newline)

会比reps 的东西简单一点。

【讨论】:

  • 在提出reps 位之前,我尝试使用 csv 模块,但发现文档有点混乱。你的例子很清楚。我会试试这个,只是为了学习。 1.你是否消除了quoting=False文本文件中的引号? 2. 你能证实我的理解吗?代码中的date 行首先拆分日期部分并自行成为列表,然后拆分daytime,其余行附加到daytime。我不确定它是如何在您的 newline = day + time + line[1] 行中自动添加逗号的。嗯……
  • @marillon: (1) 是的,有很多不同的报价选项。实际上,我认为将它们全部删除有点奇怪,但也许出于某种原因你需要它。 (2) 是的。 newline 中没有添加逗号——这只是一个列表。 writerowwriter 方法,它将逗号添加到输出字符串(或制表符或我们想要的任何其他分隔符),并在我们需要时处理引用。
  • 好的,我想我明白了。另外,您根本不需要解析该行的数据部分,因为它已经用逗号分隔了。很好的信息,非常感谢!
【解决方案3】:

有几种方法可以解决这个问题。一种选择是使用inputfile.read() 而不是inputfile.readlines() - 您需要编写单独的代码来去除前四行,但如果您希望最终输出为单个字符串,这可能是最有意义的。

第二个更简单的选择是在使用my_text = ''.join(my_text) 分割前四行后重新加入字符串。这有点低效,但如果速度不是主要问题,代码将是最简单的。

最后,如果您确实希望将输出作为字符串列表而不是单个字符串,您只需修改数据解析器以遍历列表即可。这可能看起来像这样:

def data_parser(lines, dic):
    for i, j in dic.iteritems():
        for (k, line) in enumerate(lines):
            lines[k] = line.replace(i, j)
    return lines

【讨论】: