Python читает файл до совпадения, читает до следующего шаблона - PullRequest
3 голосов
/ 14 сентября 2011

Python 2.4.3

Мне нужно прочитать некоторые файлы (может быть размером до 10 ГБ). Что мне нужно сделать, это просмотреть файл, пока он не будет соответствовать шаблону. Затем выведите эту строку и каждую строку после нее, пока она не будет соответствовать другому шаблону. После этого продолжите чтение файла до следующего совпадения с шаблоном.

Например. файл содержит.

---- Alpha ---- Zeta
...(text lines)

---- Bravo ---- Delta
...(text lines)

и т.д.

При совпадении на ---- Альфа ---- Зета, он должен печатать ---- Альфа ---- Зета и каждую строку после этого, пока не встретится ---- Браво ---- Дельта (или что-либо, кроме ---- Альфа ---- Зета), которое он будет читать прямо до тех пор, пока не будет соответствовать ---- Альфа ---- Зета снова.

Следующее соответствует тому, что я ищу - но печатает только соответствующую строку - а не текст, который следует за ним.

Есть идеи, где я ошибаюсь?

import re
fh = open('text.txt', 'r')

re1='(-)'   # Any Single Character 1
re2='(-)'   # Any Single Character 2
re3='(-)'   # Any Single Character 3
re4='(-)'   # Any Single Character 4
re5='( )'   # White Space 1
re6='(Alpha)'  # Word 1
re6a='((?:[a-z][a-z]+))'   # Word 1 alternate
re7='( )'   # White Space 2
re8='(-)'   # Any Single Character 5
re9='(-)'   # Any Single Character 6
re10='(-)'  # Any Single Character 7
re11='(-)'  # Any Single Character 8
re12='(\\s+)'  # White Space 3
re13='(Zeta)'  # Word 2
re13a='((?:[a-z][a-z]+))'  # Word 2 alternate


rg = re.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13,re.IGNORECASE|re.DOTALL)
rga =     re.compile(re1+re2+re3+re4+re5+re6a+re7+re8+re9+re10+re11+re12+re13a,re.IGNORECASE|re.DOTALL)


for line in fh:
    if re.match(rg, line):
        print line
        fh.next()
        while not re.match(rga, line):
            print fh.next()

fh.close()

и мой пример текстового файла.

---- Pappa ---- Oscar
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris eleifend imperdiet 
lacus quis imperdiet. Nulla erat neque, laoreet vel fermentum a, dapibus in sem. 
Maecenas elementum nisi nec neque pellentesque ac rutrum urna cursus. Nam non purus 
sit amet dolor fringilla venenatis. Integer augue neque, scelerisque ac dictum at, 
venenatis elementum libero. Etiam nec ante in augue porttitor laoreet. Aenean ultrices
pellentesque erat, id porta nulla vehicula id. Cras eu ante nec diam dapibus hendrerit
in ac diam. Vivamus velit erat, tincidunt id tempus vitae, tempor vel leo. Donec 
aliquam nibh mi, non dignissim justo.

---- Alpha ---- Zeta
Sed molestie tincidunt euismod. Morbi ultrices diam a nibh varius congue. Nulla velit
erat, luctus ac ornare vitae, pharetra quis felis. Sed diam orci, accumsan eget 
commodo eu, posuere sed mi. Phasellus non leo erat. Mauris turpis ipsum, mollis sed 
ismod nec, aliquam non quam. Vestibulum sem eros, euismod ut pharetra sit amet, 
dignissim eget leo.

---- Charley ---- Oscar
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. 
Aliquam commodo, metus at vulputate hendrerit, dui justo tempor dui, at posuere    
ante vitae lorem. Fusce rutrum nibh a erat condimentum laoreet. Nullam eu hendrerit 
sapien. Suspendisse id lobortis urna. Maecenas ut suscipit nisi. Proin et metus at 
urna euismod sollicitudin eu at mi. Aliquam ac egestas magna. Quisque ac vestibulum 
lectus. Duis ac libero magna, et volutpat odio. Cras mollis tincidunt nibh vel rutrum.
Curabitur fringilla, ante eget scelerisque rhoncus, libero nisl porta leo, ac
vulputate mi erat vitae felis. Praesent auctor fringilla rutrum. Aenean sapien ligula,
imperdiet sodales ullamcorper ut, vulputate at enim.


---- Bravo ---- Delta
Donec cursus tincidunt pellentesque. Maecenas neque nisi, dignissim ac aliquet ac,
vestibulum ut tortor. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Aenean ullamcorper dapibus accumsan. Aenean eros
tortor, ultrices at adipiscing sed, lobortis nec dolor. Fusce eros ligula, posuere
quis porta nec, rhoncus et leo. Curabitur turpis nunc, accumsan posuere pulvinar eget,
sollicitudin eget ipsum. Sed a nibh ac est porta sollicitudin. Pellentesque ut urna ut 
risus pharetra mollis tincidunt sit amet sapien. Sed semper sollicitudin eros quis 
pellentesque. Curabitur ac metus lorem, ac malesuada ipsum. Nulla turpis erat, congue 
eu gravida nec, egestas id nisi. Praesent tellus ligula, pretium vitae ullamcorper 
vitae, gravida eu ipsum. Cras sed erat ligula.


---- Alpha ---- Zeta
Cras id condimentum lectus. Sed sit amet odio eros, ut mollis sapien. Etiam varius 
tincidunt quam nec mattis. Nunc eu varius magna. Maecenas id ante nisl. Cras sed augue 
ipsum, non mollis velit. Fusce eu urna id justo sagittis laoreet non id urna. Nullam 
venenatis tincidunt gravida. Proin mattis est sit amet dolor malesuada sagittis. 
Curabitur in lacus rhoncus mi posuere ullamcorper. Phasellus eget odio libero, ut 
lacinia orci. Pellentesque iaculis, ligula at varius vulputate, arcu leo dignissim 
massa, non adipiscing lectus magna nec dolor. Quisque in libero nec orci vestibulum 
dapibus. Nulla turpis massa, varius quis gravida eu, bibendum et nisl. Fusce tincidunt 
laoreet elit, sed egestas diam pharetra eget. Maecenas lacus velit, egestas nec tempor 
eget, hendrerit et massa.

+++++++++++++++++++++ Обновление +++++++++++++++++++++++++ +++++++

Следующий код работает - он совпадает со строкой типа заголовка - печатает эту и каждую строку после него до следующего шаблона типа заголовка - что не соответствует, пропускает до следующего шаблона типа заголовка.

Единственная проблема - это действительно очень медленно. Через линии длиной 10 м требуется около минуты.

re1='(-)'   # Any Single Character 1
re2='(-)'   # Any Single Character 2
re3='(-)'   # Any Single Character 3
re4='(-)'   # Any Single Character 4
re5='( )'   # White Space 1
re6='(Alpha)'  # Word 1
re6a='((?:[a-z][a-z]+))'   # Word 1 alternate
re7='( )'   # White Space 2
re8='(-)'   # Any Single Character 5
re9='(-)'   # Any Single Character 6
re10='(-)'  # Any Single Character 7
re11='(-)'  # Any Single Character 8
re12='(\\s+)'  # White Space 3
re13='(Zeta)'  # Word 2
re13a='((?:[a-z][a-z]+))'  # Word 2 alternate


rg = re.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13,re.IGNORECASE|re.DOTALL)
rga = re.compile(re1+re2+re3+re4+re5+re6a+re7+re8+re9+re10+re11+re12+re13a,re.IGNORECASE|re.DOTALL)



linestop = 0
fh = open('test.txt', 'r')

for line in fh:
    if linestop == 0:
        if re.match(rg, line):
            print line
            linestop = 1
    else:
        if re.match(rga, line):
            linestop = 0
        else:
            print line

fh.close()

+++++++++ Если я сначала добавлю сюда часть grep, я думаю, что это значительно ускорит процесс. то есть grep out - затем запустите приведенный выше скрипт регулярного выражения.

У меня хорошо работает os.system - я не вижу, как передать соответствие регулярному выражению через pOpen

**** Окончательное обновление **********

Я звоню, это завершено. Я закончил тем, что сделал:

  • Grep через файл, используя os.system - и выписывая результаты.
  • чтение файла и использование re.match, который есть у меня выше - распечатка только необходимых элементов.

Чистый результат - от 65 секунд на чтение файла с 10 миллионами строк (распечатка необходимых элементов) до 3,5 секунд. Я хотел бы выяснить, как передать grep кроме os.system - но, возможно, это не очень хорошо реализовано в python 2.4

Ответы [ 2 ]

3 голосов
/ 14 сентября 2011

Я не вижу необходимости использовать регулярные выражения здесь.Не то чтобы они такие плохие, но если вы ищете такой специфический паттерн, использовать регулярные выражения просто излишне.Попробуйте что-то вроде этого:

def record(filename, pattern):
    with open(filename) as file:
        recording = False
        for line in file:
            if line.startswith(pattern):
                yield line
                recording = not recording
            elif recording:
                yield line

Вызов record с именем файла, и ваш шаблон даст вам объект генератора, выдающий строку за строкой.Это лучше, когда имеешь дело с большими файлами, поэтому вам не нужно их черпать сразу.

Печать ваших строк может тогда работать так - при условии, что ваш файл называется example.txt:

for rec in record(filename, '---- Alpha ---- Zeta'):
    print rec

Если быть точным: генератор record выдает строки, включая разрывы строк, поэтому вы можете join соединить их вместе без дополнительных разрывов строк:

print "".join(list(record(filename, '---- Alpha ---- Zeta')))
2 голосов
/ 14 сентября 2011

Вы по-прежнему сопоставляете строку, которая не меняется, потому что вы все еще находитесь в той же итерации цикла for.

...