Скажем, я хочу преобразовать текстовый файл (in.txt) в файл csv (out.csv) с помощью Python.

In.txt :

ID: 1
Name: Jon Doe
Address: 123 Main St Anytown, USA
Age: 25

Выходной файл out.csv должен выглядеть так:

"ID","Name","Address","Age"
"1","Jon Doe","123 Main St Anytown, USA","25"

Пока что я сделал это:

#!/usr/bin/python
#-*- coding:utf-8 -*-

import csv

f = open("in.txt")
x = f.readlines()
s = []

for i in x:
    i = i.replace(":",'"')
    j = i.replace(" ","'")
    
csvex = csv.writer(open("out.csv","w"), quoting=csv.QUOTE_ALL)
csvex.writerow(s)

Как я могу это сделать?

0
testFreak 10 Окт 2021 в 12:54

2 ответа

Лучший ответ

Решение, позволяющее использовать одну или несколько записей:

def read_records(fn_in, fn_out, record_size):
    with open(fn_out, 'w') as out_f:
        write_header = True
        with open(fn_in) as in_f:
            while True:
                try:
                    rec = {
                        f'"{key.strip()}"': f'"{value.strip()}"' for key, value in
                        [next(in_f).split(':') for _ in range(record_size)]
                    }
                    if write_header:
                        write_header = False
                        out_f.write(','.join(rec.keys()) + '\n')
                    out_f.write(','.join(rec.values()) + '\n')
                except StopIteration:
                    break


read_records('in.txt', 'out.csv', 4)

Некоторое объяснение:

  • все находится в функции, поэтому вы можете использовать ее многократно и для разных файлов и размеров записей
  • цикл while True повторяется бесконечно, пока из него не прервется оператор break
  • try .. except StopIteration ловит, когда next(in_f) пытается прочитать за пределами конца файла
  • rec создается как словарь, что удобно в случае, если вам нужно дополнительно манипулировать значениями или вы хотите использовать запись в другом месте, хотя, строго говоря, это не самый эффективный способ выполнения задачи.
0
Grismar 10 Окт 2021 в 10:29

Вы можете использовать регулярное выражение:

import re

data = """
ID: 1
Name: Jon Doe
Address: 123 Main St Anytown, USA
Age: 25
"""

pattern = re.compile(r'^(?P<header>[^:\n]+):\s*(?P<value>.+)', re.MULTILINE)

headers, contents = [[], []]

for m in pattern.finditer(data):
    header, content = m.groups()
    headers.append(header)
    contents.append(content)

print(headers)
print(contents)

Что даст

['ID', 'Name', 'Address', 'Age']
['1', 'Jon Doe', '123 Main St Anytown, USA', '25']

Теперь вы можете присоединиться к ним с ; или сделать с ним что-нибудь еще. См. Демонстрацию выражения на regex101.com .

0
Jan 10 Окт 2021 в 10:06