2016-02-23 3 views
2

У меня есть большое количество текстовых файлов для чтения из Python. Каждый файл структурирован как в следующем примере:Прочитать и выбрать определенные строки из текстового файла regex Python

------------------------------------------------------------------------------ 
\\ 
Paper: some_integer 
From: <some_email_address> 
Date: Wed, 4 Apr 2001 12:08:13 GMT (27kb) 
Date (revised v2): Tue, 8 May 2001 10:39:33 GMT (27kb) 

Title: some_title 
Authors: name_1, name_2 
Comments: 28 pages, JHEP latex 
\\ 
    blablabla (this is a multiline abstract of the paper) 
    blablabla 
    blablabla 
\\ 

Я хотел бы автоматически извлекать и хранить (например, в виде списка) в Title, Authors и аннотацию (текст между вторым и третьим \\ - обратите внимание, что он начинается с отступа) из каждого текстового файла. Также обратите внимание, что белая линия между Date (revised) и Title действительно существует (это не опечатка, которую я представил).

Мои попытки до сих пор повлекшие (я показываю шаги для одного текстового файла, скажем, первый файл в списке):

filename = os.listdir(path)[0] 
test = pd.read_csv(filename, header=None, delimiter="\t") 

Который дает мне:

           0 
0 ----------------------------------------------... 
1             \\ 
2         Paper: some_integer 
3       From: <some_email_address> 
4   Date: Wed, 4 Apr 2001 12:08:13 GMT (27kb) 
5 Date (revised v2): Tue, 8 May 2001 10:39:33 G... 
6        Title: some_title... 
7        Authors: name_1, name_2 
8      Comments: 28 pages, JHEP latex 
9       Report-no: DUKE-CGTP-00-01 
10             \\ 
11           blabla... 
12           blabla... 
13           blabla... 
14             \\ 

I может выбрать данную строку (например, один с изображением названия) с:

test[test[0].str.contains("Title")].to_string() 

Но это усеченный, это не чистый string (появляются некоторые атрибуты), и я считаю, что весь этот подход на основе панд довольно утомительный на самом деле ... Должен быть более простой способ прямого выбора интересующих строк из текстового файла с помощью регулярного выражения. По крайней мере, я надеюсь на это ...

+0

Может сами данные можно получить в более машиночитаемом формате, скажем XML? Если это опубликованная запись, весь db можно загрузить как xml IIRC, что очень удобно. –

ответ

1

вы можете обрабатывать по строкам.

import re 
data = {} 
temp_s = match = '' 
with open('myfile.txt', 'r') as infile: 
    for line in infile: 
      if ":" in line: 
       line = line.split(':') 
       data[line[0]] = line[1] 
      elif re.search(r'.*\w+', line): 
       match = re.search(r'(\w.*)', line) 
       match = match.group(1) 
       temp_s += match 
       while 1: 
        line = infile.next() 
        if re.search(r'.*\w+', line): 
         match = re.search(r'(\w.*)', line) 
         temp_s += match.group(1) 
        else: 
         break 
       data['abstract'] = temp_s 
+0

спасибо, кажется приятным, но я не могу запустить ваш код. Каким должен быть объект 'values'? – Antoine

+0

@ Антуан сожалеет о том, что я делал несколько пробных пробегов с приведенным выше кодом, а остатки предыдущего прогона оставались неподвижными и должны работать. – Seekheart

+0

это почти идеально. Дело только в том, что извлекается только последняя строка абстракции (хотя это не так в примере, который я предоставил, - извините, мой плохой - в реальных данных тезисы показывают несколько строк) – Antoine

1

Как насчет итерация каждой строки в файле и разделить первым :, если он присутствует в линии, собирая результат раскола в словаре:

with open("input.txt") as f: 
    data = dict(line.strip().split(": ", 1) for line in f if ": " in line) 

в результате data будет содержать:

{ 
    'Comments': '28 pages, JHEP latex', 
    'Paper': 'some_integer', 
    'From': '<some_email_address>', 
    'Date (revised v2)': 'Tue, 8 May 2001 10:39:33 GMT (27kb)', 
    'Title': 'some_title', 
    'Date': 'Wed, 4 Apr 2001 12:08:13 GMT (27kb)', 
    'Authors': 'name_1, name_2' 
} 
+0

Я думаю, что OP также хочет абстрактный. – gil

+0

точно. Этот подход хорош для всего, кроме абстрактного – Antoine

1

Если ваши файлы действительно всегда имеют ту же структуру, вы могли бы придумать:

# -*- coding: utf-8> -*- 
import re 

string = """ 
------------------------------------------------------------------------------ 
\\ 
Paper: some_integer 
From: <some_email_address> 
Date: Wed, 4 Apr 2001 12:08:13 GMT (27kb) 
Date (revised v2): Tue, 8 May 2001 10:39:33 GMT (27kb) 

Title: some_title 
Authors: name_1, name_2 
Comments: 28 pages, JHEP latex 
\\ 
    blablabla (this is the abstract of the paper) 
\\ 
""" 

rx = re.compile(r""" 
    ^Title:\s(?P<title>.+)[\n\r]  # Title at the beginning of a line 
    Authors:\s(?P<authors>.+)[\n\r]  # Authors: ... 
    Comments:\s(?P<comments>.+)[\n\r] # ... and so on ... 
    .*[\n\r] 
    (?P<abstract>.+)""", 
    re.MULTILINE|re.VERBOSE)   # so that the caret matches any line 
             # + verbose for this explanation 

for match in rx.finditer(string): 
    print match.group('title'), match.group('authors'), match.group('abstract') 
    # some_title name_1, name_2 blablabla (this is the abstract of the paper) 

Этот подход принимает Title в качестве якоря (начало строки) и затем сбрасывает текст. Названные группы могут быть действительно не нужны, но сделать код более понятным. Образец [\n\r] ищет символы новой строки.
См. a demo on regex101.com.

+0

, спасибо, единственная проблема в том, что ваш ввод - это строка. В моем случае это текстовый файл. Когда я читаю свой текстовый файл как строку (например, с 'open (filename, 'r') в качестве myfile: data = myfile.read(). Replace ('\ n', '')'), к сожалению, форматирование уничтожен ... – Antoine

+0

Просто прочитайте его как readlines(). – Jan

1

Эта модель поможет вам начать работу:

\\[^\\].*[^\\]+Title:\s+(\S+)\s+Authors:\s+(.*)[^\\]+\\+\s+([^\\]*)\n\\

Пусть 'txtfile.txt' имеет формат, как показано в верхней части. При использовании питона 2.7x:

import re 
with open('txtfile.txt', 'r') as f: 
    input_string = f.read() 
p = r'\\[^\\].*[^\\]+Title:\s+(\S+)\s+Authors:\s+(.*)[^\\]+\\+\s+([^\\]*)\n\\' 
print re.findall(p, input_string) 

Выход:

[('some_title', 'name_1, name_2', 'blablabla (this is a multiline abstract of the paper)\n blablabla\n blablabla')] 
+0

спасибо, но как я могу преобразовать свой текстовый файл в строку, сохраняющую форматирование текстового файла? Ваш подход работает только со строкой в ​​качестве входных данных. – Antoine

+0

@Antoine: Это не имеет никакого отношения к подходу, если у вас есть текстовый файл для ввода. Вам нужно прочитать текстовый файл в строке. После этого примените регулярное выражение. – Quinn

Смежные вопросы