2016-05-14 4 views
1

У меня есть файл, который я бы хотел проанализировать в csv. Файл представляет собой файл экспорта, и приходит ко мне в следующем формате (строка за строкой, каждый файл, содержащий тысячи строк):Python 3.5 csv синтаксический анализ со специальными символами

03:30:30 08:30:30 [15 August 2015] productid:123456789 manuf:987654321 case:12 pallet:1234 id:12 code:1234 12345 123 12 

Я хотел бы получить данные в файл CSV следующим образом:

local time, GMT time, date, product id, manuf id, case, pallet, id, code, company id, location, secondary code 
03:30:30, 08:30:30, 15 August 2015, 123456789, 987654321, 12, 1234, 12, 1234, 12345, 123, 12 

Я успешно сделал это, но используя неправильные инструменты, я считаю. Я использую линии, как показано ниже:

import fileinput 
for line in fileinput.FileInput("file",inplace=1): 
    line = line.replace(":",",") 

import fileinput 
for line in fileinput.FileInput("file",inplace=1): 
    line = line.replace("case"," ") 

, который дает мне что-то вроде ..

l h, l min, ls, gmt h, gmt m, gmt s, date, product id, manuf id, case, pallet, id, code, company id, location, secondary code 
03,30,30,08,30,30,15 August 2015, 123456789, 987654321, 12, 1234, 12, 1234, 12345, 123, 12 

Проблемы: Я должен использовать последовательные линии для разбора каждого символа и слова в формате CSV (дескриптор слова, двоеточия, скобки и т. д.), и на большой набор данных требуется много времени. Также я сохраняю все это во вторичном файле вместо того, чтобы писать на месте. Заменив двоеточия запятыми, мои времена разбиваются на отдельные столбцы. Я провел несколько дней, играя с разными опциями и прибыл в regex, но поскольку полный newb для python еще не придумал решение. Может быть проще восстановить время от блоков, разделенных запятыми, в правильный формат, но я в недоумении. Пожалуйста помогите. Заранее спасибо.

Edit:

Я пытался реализовать Sparkeandshine, а также версии Юлиана работоспособного решения. Я подошел ближе, чтобы получить версию Sparkeandshie для работы, но я могу только перебирать одну строку; тот фактически находится в решении, а не весь файл. Я провел последние 24 попытки попробовать разные итерации обоих решений, но безуспешно. Вот где я:

#!/usr/bin/env python 

import csv 
import os 

inputFileName = 'test.txt' 
outputFileName = 'finished.csv' 

with open(inputFileName, newline='') as inFile, open(outputFileName, 'w', newline='') as outfile: 
    r = csv.reader(inFile) 
    w = csv.writer(outfile) 

    line = '03:30:30 08:30:30 [15 August 2015] productid:123456789 manuf:987654321 case:12 pallet:1234 id:12 code:1234 12345 123 12' 
str_list = line.split() 

new_list = [str_list[0], 
     str_list[1], 
     ' '.join([item.strip('[]') for item in str_list[2:5]]), # '[15', 'August', '2015]' 
     str_list[6].split(':')[1], 
     str_list[7].split(':')[1], 
     str_list[8].split(':')[1], 
     str_list[9].split(':')[1], 
     str_list[10].split(':')[1], 
     str_list[12], 
     str_list[13] 
     ] 

with open(inputFileName, newline='') as inFile, open(outputFileName, 'w', newline='') as outfile: 
    r = csv.reader(inFile) 
    w = csv.writer(outfile) 

    for row in r: 
     w.writerow(new_list) 

Edit: Sparkandshines ниже решения работает отлично подходит для набора линий, но я обнаружил, что некоторые из моих данных имеют линии различной длины. Например, иногда несколько строк будут содержать несколько «столбцов» данных, или последние три столбца могут повторяться дважды. Чтобы обойти эту проблему, я использовал «try» и «except error, continue» для возможных длин. С помощью этого метода я получаю дубликаты строк в своем конечном файле; есть ли лучший способ использовать решение Sparkandshine с линиями различной длины? ... или проще просто найти повторяющиеся строки (путем проверки/сравнения двух/трех столбцов) и их удаления?

+0

Что вы подразумеваете под "файл является файлом экспорта"? – iulian

+0

Вы пробовали модуль csv? https://docs.python.org/3/library/csv.html?highlight=csv#module-csv – eugecm

+0

iulian, файл экспортируется из проприетарного программного обеспечения, и я не могу изменить способ его передачи. Мне нужно иметь возможность нормализовать данные, чтобы они могли использоваться моим офисом. eugecm, я пробовал, безуспешно, модуль csv. – james

ответ

1

процесса каждая строка с использованием,

line = '03:30:30 08:30:30 [15 August 2015] productid:123456789 manuf:987654321 case:12 pallet:1234 id:12 code:1234 12345 123 12' 
str_list = line.split() 

new_list = [str_list[0], 
      str_list[1], 
      ' '.join([item.strip('[]') for item in str_list[2:5]]), # '[15', 'August', '2015]' 
      str_list[6].split(':')[1], 
      str_list[7].split(':')[1], 
      str_list[8].split(':')[1], 
      str_list[9].split(':')[1], 
      str_list[10].split(':')[1], 
      str_list[12], 
      str_list[13] 
      ] 

print(new_list) 
# Output 
['03:30:30', '08:30:30', '15 August 2015', '987654321', '12', '1234', '12', '1234', '123', '12'] 

Запись в файл CSV с,

with open(filename, 'w') as f: 
    writer = csv.writer(f) 

    # write the file header 
    fieldnames = ['local time', 'GMT time', 'date', 'product id', 'manuf id', 
      'case', 'pallet', 'id', 'code', 'company id', 'location', 'secondary code'] 
    writer.writerow(fieldnames) 

    # process each line 
    for line in lines: 
     new_list = do_something() 

     writer.writerow(new_list) # write to the file 

или обработать все линии и сохранить результаты в список списков, а затем wirte в файл CSV с writerows,

writer.writerows(lists) 

Полный исходный код,

#!/usr/bin/env python 
import csv 

inputFileName = 'test.txt' 
outputFileName = 'finished.csv' 

with open(outputFileName, 'w') as outfile: 
    w = csv.writer(outfile) 

    # write the file header 
    fieldnames = ['local time', 'GMT time', 'date', 'product id', 'manuf id', 
      'case', 'pallet', 'id', 'code', 'company id', 'location', 'secondary code'] 
    writer.writerow(fieldnames) 


    # process each line 
    with open(inputFileName, 'r') as inFile: 
     for line in inFile: 
      str_list = line.rstrip().split() 
      new_list = [str_list[0], 
         str_list[1], 
         ' '.join([item.strip('[]') for item in str_list[2:5]]), # '[15', 'August', '2015]' 
         str_list[6].split(':')[1], 
         str_list[7].split(':')[1], 
         str_list[8].split(':')[1], 
         str_list[9].split(':')[1], 
         str_list[10].split(':')[1], 
         str_list[12], 
         str_list[13]] 

      w.writerow(new_list) # write to the file 
+1

Eureka! Очень ценю помощь. Бит с именами полей для заголовка файла по-прежнему не выполняет итерацию, но не стоит беспокоиться, я знаю, как добавить строку заголовка после этой функции, чтобы это произошло. Внимательно оцените ваши быстрые ответы и рекомендации по решению этой проблемы для меня. Я провел DAYS поиск в Интернете, пытаясь решить эту проблему или узнать решение; Я буду использовать этот метод для других подобных сценариев. – james

0

Если у вас есть известная структура ваших входных файлов, вам не нужно использовать регулярные выражения, так как они медленнее. В вашем случае, попробуйте использовать что-то похожее на код ниже:

import csv 
with open('destination.csv', 'w', newline='') as csvfile: 
    csv_writer = csv.writer(csvfile, delimiter=',') 
    ... # get your data here, the next code is for one line of data 
    values = line.split() 
    values[2] = '{} {} {}'.format(values[2][1:], values[3], values[4][:-1]) # Get rid of square brackets 
    for idx in range(5, 11): 
     values[idx] = values[idx].split(':')[1] # get the number values 
    values.pop(3); # remove separated month name 
    values.pop(3); # remove separated year 

    csv_writer.writerow(values) 

Вы редактируете только те данные, которые требуют его, а затем записать всю строку в файл CSV.

+0

'line.split()' splits' [15 августа 2015] 'as' '[15', 'August', '2015]' '(3 элемента' values'). Итак, 'values ​​[2] = values ​​[2] [1: -1]' возвращает '1'. – SparkAndShine

+1

@sparkandshine мой плохой, был не очень внимателен. исправлено это сейчас – iulian

Смежные вопросы