2016-05-14 57 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(描述符詞,冒號,括號等),並且在大型數據集上花費很長時間。另外,我將它全部保存到輔助文件中,而不是寫入到位。通過用逗號替換冒號,我的時間被分解成單獨的列。我花了幾天時間玩不同的選項,併到達正則表達式,但作爲一個完整的Python新手尚未提出解決方案。從逗號分隔的塊重建時間到正確的格式可能會更簡單,但我很茫然。請協助。提前致謝。

編輯:

我試圖實現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) 

編輯:Sparkandshines以下解決方案的偉大工程組行,但我發現我的一些數據具有不同長度的線路。例如,有時幾行會縮短一些「列」數據,或者最後三列可能會重複兩次。爲了解決這個問題,我一直在使用「嘗試」和「除了錯誤,繼續」可能的長度。用這種方法,我在我的最終文件中得到重複的行;有沒有更好的方法來使用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

尤里卡!真的很感謝幫助。文件頭的字段名仍然不會迭代,但不用擔心,我知道如何在此函數之後插入標題行以實現此目的。非常感謝您爲我解決這個問題的快速反應和指導。我花了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()'split [2015年8月15日]''[15','August','2015]''('values'的3個元素)。所以,'values [2] = values [2] [1:-1]'返回'1'。 – SparkAndShine

+1

@sparkandshine我的不好,不是很細心。立即修復它 – iulian