2017-02-26 63 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

相关问题