2015-05-09 2 views
1

У меня есть текстовый файл в следующем формате:Чтение структурированный текстовый файл в Python

1. AUTHOR1 

(blank line, with a carriage return) 

Citation1 

2. AUTHOR2 

(blank line, with a carriage return) 

Citation2 

(...) 

То есть, в этом файле, некоторые строки начинаются с целым числом, за которым следует точка, пробел, и текст с указанием имени автора; за этими строками следует пустая строка (которая включает возврат каретки), а затем для строки текста, начинающейся с буквенного символа (цитирования статьи или книги).

То, что я хочу, чтобы прочитать этот файл в список Python, присоединившись имена автора и цитаты, так что каждый элемент списка имеет вид:

[ «AUTHOR1 Citation1», «AUTHOR2 Citation2» , '...']

Это похоже на простую проблему программирования, но я не мог решить, какое именно решение. Я попытался сделать следующее:

articles = [] 
with open("sample.txt", "rb") as infile: 
    while True: 
     text = infile.readline() 
     if not text: break 
     authors = "" 
     citation = "" 
     if text == '\n': continue 
     if text[0].isdigit(): 
      authors = text.strip('\n') 
     else: 
      citation = text.strip('\n' 
     articles.append(authors+' '+citation) 

но список статей содержит авторов и цитаты, хранящиеся в виде отдельных элементов! .

Заранее спасибо за любую помощь в решении этой неприятной проблемы ... :-(

ответ

1

Вы можете использовать Readline пропускать пустые строки Вот ваше тело цикла:

author = infile.readline().strip().split(' ')[1] 
infile.readline() 
citation = infile.readline() 
articles.append("{} {}".format(author, citation)) 
1

Проблема заключается в том что в каждой циклической итерации вы получаете только одну, автору или цитату и не оба. Итак, когда вы добавляете, у вас есть только один элемент.

Один из способов исправить это - читать как в каждая циклическая итерация.

1

Это должно работать:

articles = [] 
with open("sample.txt") as infile: 
    for raw_line in infile: 
     line = raw_line.strip() 
     if not line: 
      continue 
     if line[0].isdigit(): 
      author = line.split(None, 1)[-1] 
     else: 
      articles.append('{} {}'.format(author, line)) 
+0

Спасибо, это решило мою проблему! – maurobio

+1

@maurobio Отлично. Не стесняйтесь принять мой ответ. –

2

Если предположить, что входную структуру файла:

""" 
1. AUTHOR1 

Citation1 
2. AUTHOR2 

Citation2 
""" 

не собирается менять я хотел бы использовать readlines() и нарезку:

with open('sample.txt', 'r') as infile: 
    lines = infile.readlines() 
    if lines: 
     lines = filter(lambda x : x != '\n', lines) # remove empty lines 
     auth = map(lambda x : x.strip().split('.')[-1].strip(), lines[0::2]) 
     cita = map(lambda x : x.strip(), lines[1::2]) 
     result = [ '%s %s'%(auth[i], cita[i]) for i in xrange(len(auth)) ] 
     print result 

# ['AUTHOR1 Citation1', 'AUTHOR2 Citation2'] 
1

Решения обработку полный ввод в каждой итерации цикла:

citations = [] 
with open('sample.txt') as file: 
    for author in file:     # Reads an author line 
     next(file)      # Reads and ignores the empty line 
     citation = next(file).strip() # Reads the citation line 
     author = author.strip().split(' ', 1)[1] 
     citations.append(author + ' ' + citation) 
print(citations) 

Решение первое чтение все строки, а затем проходит через них:

citations = [] 
with open('sample.txt') as file: 
    lines = list(map(str.strip, file)) 
    for author, citation in zip(lines[::3], lines[2::3]): 
     author = author.split(' ', 1)[1] 
     citations.append(author + ' ' + citation) 
print(citations) 
1

Растворы на основе нарезку довольно аккуратно, но если есть только одна пустая строка неуместна, она бросает все это прочь , Вот решение с использованием регулярного выражения, которое должно работать, даже если есть изменения в структуре:

import re 

pattern = re.compile(r'(^\d\..*$)\n*(^\w.*$)', re.MULTILINE) 
with open("sample.txt", "rb") as infile: 
    lines = infile.readlines() 
matches = pattern.findall(lines) 
formatted_output = [author + ' ' + citation for author, citation in matches]