2011-08-17 33 views
10

Tôi có một tập tin văn bản trong định dạng sau:Liên tiếp trích xuất một ranh giới giữa hai delimiters trong một file văn bản, Python

DELIMITER1 
extract me 
extract me 
extract me 
DELIMITER2 

Tôi muốn trích xuất tất cả các khối extract me s giữa DELIMITER1 và DELIMITER2 trong .txt tập tin

Đây là hiện tại, không thực hiện mã của tôi:

import re 
def GetTheSentences(file): 
    fileContents = open(file) 
    start_rx = re.compile('DELIMITER') 
    end_rx = re.compile('DELIMITER2') 

    line_iterator = iter(fileContents) 
    start = False 
    for line in line_iterator: 
      if re.findall(start_rx, line): 

       start = True 
       break 
     while start: 
      next_line = next(line_iterator) 
      if re.findall(end_rx, next_line): 
       break 

      print next_line 

      continue 
     line_iterator.next() 

Bất kỳ ý tưởng?

Trả lời

16

Bạn có thể đơn giản hóa này với một biểu thức chính quy dùng re.S, các DOTALL flag.

import re 
def GetTheSentences(infile): 
    with open(infile) as fp: 
     for result in re.findall('DELIMITER1(.*?)DELIMITER2', fp.read(), re.S): 
      print result 
# extract me 
# extract me 
# extract me 

này cũng làm cho việc sử dụng nhà điều hành không tham lam .*?, vì vậy nhiều khối không chồng chéo của các cặp DELIMITER1-DELIMITER2 tất cả sẽ được tìm thấy.

+3

: sử dụng thẻ này với đối tượng tệp được ánh xạ bộ nhớ (thông qua mô-đun 'mmap') nếu tệp của bạn quá lớn để đọc trong cùng một lúc. – Steven

+0

@Brent Đã thử điều này và nó hoạt động độc đáo ... Cảm ơn! – Renklauf

+0

Vui vì tôi có thể giúp. Đừng quên đánh dấu câu trả lời là được chấp nhận nếu đó là câu trả lời hay nhất cho câu hỏi của bạn. –

2

này nên làm những gì bạn muốn:

import re 
def GetTheSentences(file): 
    start_rx = re.compile('DELIMITER') 
    end_rx = re.compile('DELIMITER2') 

    start = False 
    output = [] 
    with open(file, 'rb') as datafile: 
     for line in datafile.readlines(): 
      if re.match(start_rx, line): 
       start = True 
      elif re.match(end_rx, line): 
       start = False 
      if start: 
        output.append(line) 
    return output 

phiên bản trước đó của bạn có vẻ như nó là nghĩa vụ phải là một chức năng lặp. Bạn có muốn đầu ra của bạn trả lại một mục tại một thời điểm không? Đó là hơi khác nhau.

+0

Không cần đọc toàn bộ tệp vào bộ nhớ. Bạn cũng không cần cụm từ thông dụng nếu nó đơn giản như tìm chuỗi con cụ thể trong một dòng. – agf

+0

@agf Tất nhiên là không, nhưng ví dụ đơn giản của anh ta có thể không chính xác tương ứng với dữ liệu của anh ta. Tôi đã thực hiện một điều rất giống với một tệp postscript, và tôi hoàn toàn phải có các biểu thức chính quy cho điểm bắt đầu và kết thúc của mình. –

+0

@everyone cảm ơn tất cả sự giúp đỡ về điều này! – Renklauf

2

Nếu delimiters nằm trong một dòng:

def get_sentences(filename): 
    with open(filename) as file_contents: 
     d1, d2 = '.', ',' # just example delimiters 
     for line in file_contents: 
      i1, i2 = line.find(d1), line.find(d2) 
      if -1 < i1 < i2: 
       yield line[i1+1:i2] 


sentences = list(get_sentences('path/to/my/file')) 

Nếu họ đang ở trên đường riêng của họ:

def get_sentences(filename): 
    with open(filename) as file_contents: 
     d1, d2 = '.', ',' # just example delimiters 
     results = [] 
     for line in file_contents: 
      if d1 in line: 
       results = [] 
      elif d2 in line: 
       yield results 
      else: 
       results.append(line) 

sentences = list(get_sentences('path/to/my/file')) 
+0

Traceback (gần đây nhất gọi cuối cùng): File "", dòng 1, trong File "", dòng 10, trong get_sentences UnboundLocalError: biến cục bộ ' kết quả 'được tham chiếu trước khi gán – amadain

+0

@amadain Tôi đã thêm một dòng để khởi tạo kết quả, nhưng nhìn vào điều này, tôi không chắc là nó có đúng không. Mẹo – agf

0

Đây là một công việc tốt cho việc hiểu Danh sách, không yêu cầu regex. Danh sách đầu tiên comp tẩy sạch các \n điển hình trong danh sách dòng văn bản được tìm thấy khi mở tệp txt. Danh sách thứ hai comp chỉ sử dụng toán tử in để xác định các mẫu trình tự để lọc.

def extract_lines(file): 
    scrubbed = [x.strip('\n') for x in open(file, 'r')] 
    return [x for x in scrubbed if x not in ('DELIMITER1','DELIMITER2')] 
Các vấn đề liên quan