在 python 中解析文本文件并输出到 CSV

Posted

技术标签:

【中文标题】在 python 中解析文本文件并输出到 CSV【英文标题】:Parsing a text file in python and outputting to a CSV 【发布时间】:2015-11-15 14:27:15 【问题描述】:

前言 - 我对 Python 还是很陌生,在其他语言方面有更多经验。

我有一个文本文件,其中包含通用(但略有不同)格式“./abc123a1/type/1ab2_x_data_type.file.type”的单列字符串列表

我需要从所有数百行中提取 abc123a1 和 1ab2 部分,并将它们放在 csv 中的两列(a 和 b 列)下。有时可能会有一个“1ab2_a”和一个“1ab2_b”,但我想要一个 1ab2。所以我想抓住“1ab2_a”并忽略所有其他人。

我有我认为可以工作的正则表达式:

tmp = list()
if re.findall(re.compile(r'^([a-zA-Z0-9]4)_'), x):
    tmp = re.findall(re.compile(r'^([a-zA-Z0-9]4)_'), x)
elif re.findall(re.compile(r'_([a-zA-Z0-9]4)_'), x):
    tmp = re.findall(re.compile(r'_([a-zA-Z0-9]4)_'), x)
if len(tmp) == 0:
    return None
elif len(tmp) > 1:
    print "ERROR found multiple matches"
    return "ERROR"
else:
    return tmp[0].upper()

我正在尝试逐步制作此脚本并进行测试以确保它有效,但事实并非如此。

import sys
import csv

listOfData = []

with open(sys.argv[1]) as f:
    print "yes"
    for line in f:
        print line
    for line in f:
        listOfData.append([line])
print listOfData

with open('extracted.csv', 'w') as out_file:
    writer = csv.writer(out_file)
    writer.writerow(('column a', 'column b'))
    writer.writerows(listOfData)

print listOfData

除了列标题之外,仍然无法在 csv 中获取任何内容,更不用说解析版本了!

有没有人有更好的想法或格式可以做到这一点?一位朋友提到要研究 glob.glob,但我也没有运气让它工作。

【问题讨论】:

当你打印listOfData时,它有你想要的数据吗? "所以我想抓住 "1ab2_a" 而忽略所有其他的。" 不确定是否能很好地理解这句话。您要提取1ab2 还是1ab2_a 您能否编辑问题以添加更多示例输入行?还要添加该输入的预期输出。 【参考方案1】:

恕我直言,您离成功不远了。问题是您读取整个文件只是为了打印行,然后(在文件末尾)尝试将它们放入列表中......并得到一个空列表!

你应该只读一次文件:

import sys
import csv

listOfData = []

with open(sys.argv[1]) as f:
    print "yes"
    for line in f:
        print line
        listOfData.append([line])
print listOfData

with open('extracted.csv', 'w') as out_file:
    writer = csv.writer(out_file)
    writer.writerow(('column a', 'column b'))
    writer.writerows(listOfData)

print listOfData

一旦成功,您仍然需要使用正则表达式来获取相关数据以放入 csv 文件中

【讨论】:

【参考方案2】:

我不确定您的正则表达式(它很可能不起作用),但是您当前的(非正则表达式,简单)代码不起作用的原因是 -

with open(sys.argv[1]) as f:
    print "yes"
    for line in f:
        print line
    for line in f:
        listOfData.append([line])

如您所见,您首先迭代文件中的每一行并打印它,应该没问题,但循环结束后,文件指针位于文件末尾,因此再次尝试迭代它会不产生任何结果。您应该只对其进行一次迭代,并在其中进行打印和附加到列表。示例 -

with open(sys.argv[1]) as f:
    print "yes"
    for line in f:
        print line
        listOfData.append([line])

【讨论】:

【参考方案3】:

我认为至少部分问题在于以下两个for 循环:

with open(sys.argv[1]) as f:
    print "yes"
    for line in f:
        print line
    for line in f:
        listOfData.append([line])

第一个prints 是f 的所有行,所以第二个没有什么可以迭代的,除非你先f.seek(0) 并倒回文件。

另一种方法可以简单地做到这一点:

with open(sys.argv[1]) as f:
    print "yes"
    for line in f:
        print line
        listOfData.append([line])

如果没有超过一行的示例输入数据,很难判断您的正则表达式是否正常。

【讨论】:

【参考方案4】:

你确定你需要所有的正则表达式吗?您似乎正在解析路径和文件名列表。可以使用split 命令拆分路径,例如:

print "./abc123a1/type/1ab2_a_data_type.file.type".split("/")

愿意:

['.', 'abc123a1', 'type', '1ab2_a_data_type.file.type']

然后您可以创建一个 set,其中包含第二个条目和第四个条目中的“_”,例如

('abc123a1', '1ab2')

这可用于仅打印每个条目的第一个条目:

pairs = set()

with open(sys.argv[1], 'r') as in_file, open('extracted.csv', 'wb') as out_file:
    writer = csv.writer(out_file)

    for row in in_file:
        folders = row.split("/")
        col_a = folders[1]
        col_b = folders[3].split("_")[0]

        if (col_a, col_b) not in pairs:
            pairs.add((col_a, col_b))
            writer.writerow([col_a, col_b])

所以对于这样的输入:

./abc123a1/type/1ab2_a_data_type.file.type
./abc123a1/type/1ab2_b_data_type.file.type
./abc123a2/type/1ab2_a_data_type.file.type
./abc123a3/type/1ab2_a_data_type.file.type

你会得到一个 CSV 文件,如下所示:

abc123a1,1ab2
abc123a2,1ab2
abc123a3,1ab2

【讨论】:

以上是关于在 python 中解析文本文件并输出到 CSV的主要内容,如果未能解决你的问题,请参考以下文章

Python:忽略文本文件的注释,该文本文件被解析为字典以写入 CSV [重复]

遇到多线程问题同时连接到多个设备

python 从文本中提取每一行的特定字符串输出到csv文件

我们有许多 EBCDIC 格式的大型机文件,Python 中有没有办法将大型机文件解析或转换为 csv 文件或文本文件?

将数据文件附加到 CSV 文件并输出到另一个 CSV 文件

解析纯文本并在android中生成csv