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

3
前言 - 我对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时,它是否包含你想要的数据? - Joseph Stover
“所以我想提取“1ab2_a”,忽略其他所有内容。” 不太确定理解这句话的意思。您是想提取“1ab2”还是“1ab2_a”? - Casimir et Hippolyte
你能否编辑问题并添加更多的示例输入行?同时,还需说明该输入的预期输出结果。 - Martin Evans
4个回答

2

在我看来,你离让它工作并不远。问题在于你一次性读取整个文件以打印行,然后(在文件结尾处)尝试将它们放入列表中...结果得到了一个空列表!

你应该只读取一次文件:

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文件中。

0

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

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])

0

我认为问题至少部分出在以下代码中的两个 for 循环:

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

第一个 print 打印了文件 f 的所有行,因此除非您首先使用 f.seek(0) 并倒回文件,否则第二个迭代器不会有任何内容可迭代。

另一种替代方法是:

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

如果没有超过一行的示例输入数据,很难确定你的正则表达式是否正确。


0

你确定需要所有的正则表达式吗?看起来你正在解析路径和文件名列表。可以使用 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接