2011-08-17 11 views
10

Mam plik tekstowy w następującym formacie:Wielokrotnie wyodrębnić linię pomiędzy dwoma ogranicznikami w pliku tekstowym, Python

DELIMITER1 
extract me 
extract me 
extract me 
DELIMITER2 

chciałbym wyodrębnić każdy blok extract me s pomiędzy DELIMITER1 i DELIMITER2 w txt

to jest mój obecny, nieregularnych Kod:

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() 

Jakieś pomysły?

Odpowiedz

16

Można uprościć to do jednego wyrażenia regularnego, używając re.S, w 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 

ten również wykorzystuje nie-chciwego operatora .*?, tak wielu nie nakładających się bloków par DELIMITER1-DELIMITER2 będzie być znaleziony.

+3

wskazówka: użyj tego w przypadku obiektu pliku odwzorowanego w pamięci (przez moduł 'mmap'), jeśli twój plik jest zbyt duży, aby można go było przeczytać od razu. – Steven

+0

@Brent Wypróbowałem to i działa ładnie ... Dzięki! – Renklauf

+0

Cieszę się, że mogę pomóc. Nie zapomnij zaznaczyć odpowiedzi jako zaakceptowanej, jeśli jest to najlepsza odpowiedź na twoje pytanie. –

2

ten powinien robić to, co chcesz:

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 

poprzedniej wersji wygląda to miało być iterator. Czy chcesz, aby Twoje dane wyjściowe zwracały jeden przedmiot na raz? To trochę inaczej.

+0

Nie trzeba czytać całego pliku w pamięci. Nie potrzebujesz również wyrażeń regularnych, jeśli jest to coś tak prostego, jak znalezienie konkretnego podciągu w linii. – agf

+0

@agf Oczywiście nie, ale jego uproszczony przykład może nie odpowiadać dokładnie jego danym. Zrobiłem bardzo podobną rzecz w stosunku do pliku postscriptowego i absolutnie musiałem mieć wyrażenia regularne dla moich punktów początkowych i końcowych. –

+0

@ everyryone dzięki za pomoc w tej sprawie! – Renklauf

2

Jeśli ograniczniki są w linii:

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')) 

Jeśli są na własnych liniach:

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 (najnowsza wezwanie ostatni): Plik „”, wiersz 1, w pliku „”, linia 10, w get_sentences UnboundLocalError: zmienna lokalna " wyniki "odniesienia przed przypisaniem – amadain

+0

@amadain Dodałem linię, aby zainicjować wyniki, ale patrząc na to, nie jestem pewien, czy i tak jest poprawna. – agf

0

Jest to dobra robota dla listy zrozumiałej, nie jest wymagane wyrażenie regularne. Pierwszy zestaw wyszukuje typową \n na liście linii tekstowej znalezionej podczas otwierania pliku txt. Druga lista używa tylko operatora in do identyfikacji wzorców sekwencji do filtrowania.

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')] 
Powiązane problemy