Python 2.5.2: удалить то, что найдено между двумя строками, которые содержат две конкретные строки - PullRequest
0 голосов
/ 05 апреля 2010

есть ли способ удалить то, что найдено между двумя строками, содержащими две бетонные строки?

Я имею в виду: я хочу удалить все, что найдено между «небесами» и «адом» в текстовом файле с таким текстом:

I'm in heaven
foobar
I'm in hell

После выполнения скрипта / функции, я спрашиваю, текстовый файл будет пустым.

Ответы [ 5 ]

3 голосов
/ 05 апреля 2010

Используйте флаг, чтобы указать, пишете вы или нет.

from __future__ import with_statement

writing = True

with open('myfile.txt') as f:
    with open('output.txt') as out:
        for line in f:
            if writing:
                if "heaven" in line:
                    writing = False
                else:
                    out.write(line)
            elif "hell" in line:
                writing = True    
os.remove('myfile.txt')
os.rename('output.txt', 'myfile.txt')

EDIT

Как указано в комментариях extraneon , необходимо удалить линии между двумя бетонными нитями. Это означает, что если вторая (закрывающая) строка не найдена, ничего не должно быть удалено. Этого можно достичь, сохранив буфер строк. Буфер отбрасывается, если найдена закрывающая строка "I'm in hell", но если конец файла достигнут, не найдя его, все содержимое должно быть записано в файл.

Пример:

I'm in heaven
foo
bar

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

Вот пример для завершения:

from __future__ import with_statement

writing = True
with open('myfile.txt') as f:
    with open('output.txt') as out:
        for line in f:
            if writing:
                if "heaven" in line:
                    writing = False
                    buffer = [line]
                else:
                    out.write(line)
            elif "hell" in line:
                writing = True
            else:
                buffer.append(line)
        else:
            if not writing:
                #There wasn't a closing "I'm in hell", so write buffer contents
                out.writelines(buffer)

os.remove('myfile.txt')
os.rename('output.txt', 'myfile.txt')
1 голос
/ 05 апреля 2010

Похоже, под «удалить» вы подразумеваете «переписать входной файл на месте» (или сделать так, как будто вы это делаете ;-), в этом случае fileinput.input помогает:

import fileinput
writing = True
for line in fileinput.input(['thefile.txt'], inplace=True):
    if writing:
        if 'heaven' in line: writing = False
        else: print line,
    else:
        if 'hell' in line: writing = True
0 голосов
/ 05 апреля 2010

см. Ниже. Я не знаю, нормально ли это, но, кажется, работает нормально.

import re,fileinput,os


for path, dirs, files in os.walk(path):
    for filename in files:
        fullpath = os.path.join(path, filename)


        f = open(fullpath,'r')


        data = f.read()

        patter = re.compile('Im in heaven.*?Im in hell', re.I | re.S)
        data = patter.sub("", data)

        f.close()

        f = open(fullpath, 'w')

        f.write(data)
        f.close()

В любом случае, когда я его выполняю, он оставляет пустую строку. Я имею в виду, если есть эта функция:

public function preFetchAll(Doctrine_Event $event){ 
//Im in heaven
$a = sfContext::getInstance()->getUser()->getAttribute("passw.formulario");
var_dump($a);
//Im in hell
foreach ($this->_listeners as $listener) {
    $listener->preFetchAll($event);
}
}

и я выполняю свой скрипт, я получаю это:

public function preFetchAll(Doctrine_Event $event){ 

foreach ($this->_listeners as $listener) {
    $listener->preFetchAll($event);
}
}

Как видите, между "public ..." и "foreach ..." есть пустая строка.

Почему?

* 1014 Javi *

0 голосов
/ 05 апреля 2010

Вы можете сделать что-то вроде следующего с регулярными выражениями. Вероятно, есть более эффективные способы сделать это, так как я все еще изучаю много Python, но это должно сработать.

import re

f = open('hh_remove.txt')
lines = f.readlines()

pattern1 = re.compile("heaven",re.I)
pattern2 = re.compile("hell",re.I)

mark1 = False
mark2 = False

for i, line in enumerate(lines):
    if pattern1.search(line) != None:
        mark1 = True
        set1 = i
    if pattern2.search(line) != None:
        mark2 = True
        set2 = i+1
    if ((mark1 == True) and (mark2 == True)):
        del lines[set1:set2]
        mark1 = False
        mark2 = False

f.close()
out = open('hh_remove.txt','w')
out.write("".join(lines))
out.close()
0 голосов
/ 05 апреля 2010

Я прошу прощения, но это звучит как домашнее задание. У нас есть политика по этим вопросам: https://meta.stackexchange.com/questions/10811/homework-on-stackoverflow

Однако я могу сказать, что функция, о которой @nosklo писал о , доступна в любом Python 2.5.x (или новее), но вам нужно изучить достаточно Python, чтобы включить его. : -)

Мое решение будет включать в себя создание новой строки с удалением нежелательного содержимого с использованием str.find() или str.index() (или некоторого родственника из этих 2).

Удачи!

...