2017-02-26 65 views
-1

我是Python新手。我有成千上萬的CSV文件,其中有一組文本在數字數據記錄後出現,我想刪除所有以文本開頭的行。例如:使用正則表達式從CSV文件中刪除包含最後一行的「字符串」

col 1 col 2 col 3 
-------------------- 
10  20  30 
-------------------- 
45  34  56 
-------------------- 
Start 8837sec 9items 
-------------------- 
Total 6342sec 755items 

好的是,所有csv文件的文本都以column1中的「Start」開始。我寧願刪除之後的所有行,包括說「開始」的行。

這是我到目前爲止有:

import csv, os, re, sys 


fileList = [] 

pattern = [r"\b(Start).*", r"\b(Total).*"] 

for file in files: 
    fullname = os.path.join(cwd, file) 

    if not os.path.isdir(fullname) and not os.path.islink(fullname): 
     fileList.append(fullname) 


for file in fileList: 
    try: 
     ifile = open(file, "r") 
    except IOError: 
     sys.stderr.write("File %s not found! Please check the filename." %(file)) 
     sys.exit() 
    else: 
     with ifile: 
      reader = csv.reader(ifile) 
      writer = csv.writer(ifile) 
      rowList = []  
      for row in reader: 
       rowList.append((", ".join(row))) 

     for pattern in word_pattern: 
      if not (re.match(pattern, rowList) 
       writer.writerow(elem) 

運行此腳本後,它給了我空白的csv文件。任何想法改變什麼?

+0

本例中沒有名爲'writer'的變量。你應該得到一個例外,並沒有寫入。你只是想在「開始」之後去掉所有的東西?你不需要csv。 – tdelaney

+0

什麼是CSV的編碼?它是ASCII還是UTF-8? – tdelaney

+0

我在代碼中添加了寫作者聲明。 CSV文件的編碼採用ASCII格式。 – SalN85

回答

0

這不需要CSV閱讀器。您可以簡單地找到偏移量並截斷文件。以二進制模式打開文件,並使用多行正則表達式在文本中查找模式並使用其索引。

import os 
import re 

# multiline, ascii only regex matches Start or Total at start of line 
start_tag_finder = re.compile(rb'(?am)\nStart|\nTotal').search 

for filename in files: # TODO: I'm not sure where "files" comes from... 
    # NOTE: no need to join cwd, relative paths do that automatically 
    if not os.path.isdir(filename) and not os.path.islink(filename): 
     with open(filename, 'rb+') as f: 
      # NOTE: you can cap file size if you'd like 
      if os.stat(filename).st_size > 1000000: 
       print(filename, "overflowed 10M size limit") 
       continue 
      search = start_tag_finder(f.read()) 
      if search: 
       f.truncate(search.start()) 
+0

嗨tdelaney ...謝謝,它確實工作:)。一個簡單的問題:在這些情況下,字符串方法(string.startswith(keywords))是否也可以工作,其中我的關鍵字是關鍵字=(「Search」,「Total」)? – SalN85

+0

這個例子在一個塊中處理文件,而不是逐行處理,所以'startswith'不起作用,但是在f.read()中會用'\ nStart'。正則表達式允許您在一個C擴展塊中同時檢查多個關鍵字,我認爲它更快。在大多數現代計算機上,燒幾兆RAM來讀取文件是微不足道的,這(猜測!)應該具有良好的性能。你可以逐行閱讀,也可以用'startswith'。 – tdelaney

0

我會嘗試這一切你得到你的fileList在一起後:

for file in fileList: 
    keepRows = [] 
    open(file, 'r') as oFile: 
    for row in oFile: 
     if row[0] != "Start": 
      keepRows += row 
     else: 
      oFile.close() 
    with open(file, 'wb+') as nFile: 
    writer = csv.writer(nFile, delimiter=',') 
    writer.writerow([keepRows]) 

這將打開你的原始文件,讓你想要的線,關閉它,並與w+打開它。這將覆蓋文件,保留名稱,但通過截斷將其清除,然後將每個要保留在清除文件每一行上的行寫入。

或者,你可以爲每個CSV做創建一個新的文件:

for file in fileList: 
    keepRows = [] 
    with open(file, 'r') as oFile, open('new_file.csv', 'a') as nFile: 
    for row in oFile: 
     if row[0] != "Start": 
      keepRows += row 
     else: 
      oFile.close() 
    for row in keepRows: 
     nFile.write(row) 

洞口a把光標的下一行,因爲這每一次都是append英寸.writerow方法在用戶迭代之前,這就是爲什麼它在[]objectobject其中每個組或row,keepRows而在append不需要迭代,並將分組內的每個項目寫入其自己的列,移動到下一個排和做同樣的事情。

編輯:更新了binary file mode.writer()的語法。

+0

嗨pstatix,謝謝你的幫助。我明白你的第一個方法是在「開始」之後通過隔離任何東西來創建一個新列表。但是,當您開始覆蓋文件時,保留名稱,我看不到截斷選項。另外,我相信csv.writer()應該把'nfile'作爲參數? – SalN85

+0

@Salil Nanda,我更新了'.writer()'部分,因爲你是正確的,我忘了給它提供一個文件對象。截斷選項基於您調用'open()'函數的模式。使用'w'意味着使用'b'''寫''意味着文件以'binary'模式打開並使用'+'啓用'讀寫'更新功能。默認情況下,'w +'將文件覆蓋爲0字節(即截斷它)。這就是爲什麼我們在收集完所需的行之後調用了「wb +」模式。我們使用'b'的原因是Windows操作系統可以解釋文件的'new line'方面。 – pstatix

+0

@Salil Nandra,回覆時間太長。下面是'open()'模式的一些參考:1)http://stackoverflow.com/questions/16208206/confused-by-python-file-mode-w。 2)https://docs.python.org/2/library/functions.html#open – pstatix

相關問題