Скопируйте все строки между двумя строками, которые не находятся в начале строки- python - PullRequest
2 голосов
/ 14 января 2020

Я новичок в этом мире, и мне нужно сделать это с таким файлом:


...... | 4751 | ......

.
.
.
. , , 99999 |

Я хочу найти эту строку "| 4751 |" и скопировать все строки и строку со строкой "| 4751 |" до строки, содержащей 99999 |

Текст имеет кратные «| 4751 |» и 99999 | и я хочу скопировать все строки между ними

Возможно ли это с python? Я нашел здесь несколько постов, но проблема в том, что я не могу адаптировать скрипт, потому что моя строка | 4751 | находится в середине ряда, а не в его начале.

Ответы [ 2 ]

3 голосов
/ 15 января 2020

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

class Collector:
    def __init__(self, filename, start_marker, stop_marker):
        self.toggle_collect = False
        self.f = open(filename)
        self.m1 = start_marker
        self.m2 = stop_marker

    def __enter__ (self):
        return self

    def __exit__ (self, exc_type, exc_value, traceback):
        self.f.close()

    def __iter__(self):
        return self

    def __next__(self):
        while True:
            r = next(self.f)
            if self.m1 in r:  # found the start-collecting marker
                self.toggle_collect = True
            elif self.m2 in r:  # found the stop-collecting marker
                self.toggle_collect = False
                continue
            if self.toggle_collect:  # we are collecting
                return r.rstrip()  # collect row


with Collector('file_rows.txt', '4751', '99999') as c:
    for r in c:
        print(r)

, который при входном файле

foobar0
foo|4751|bar1
foobar2
foo99999|bar3
foobar4
foobar5
foo|4751|bar6
foo99999|bar7
foobar8

производит

foo|4751|bar1

foobar2

foo|4751|bar6

Примечание. Как видно из выходных данных, строки разделены пустой строкой. Это потому, что они включают возврат каретки.

Если это не нужно, мы можем удалить его

            if self.toggle_collect:  # we are collecting
                return r.rstrip()  # provide row

В случае, если нам нужны строки в списке, просто создайте одну из итератора

with Collector('file_rows.txt', '4751', '99999') as c:
    results = list(c)
2 голосов
/ 14 января 2020

Вы можете использовать re.findall с re.MULTILINE|re.DOTALL флагами и предвкушением. Обязательно экранируйте символы |, которые имеют особое значение в регулярных выражениях:

import re

haystack = """foobar0
foo|4751|bar1
foobar2
foo99999|bar3
foobar4
foobar5
foo|4751|bar6
foo99999|bar7
foobar8"""

needle = "^[^\n]*\|4751\|.*?(?=99999\|)"
result = re.findall(needle, haystack, re.MULTILINE|re.DOTALL)

print (result)

, что приводит к:

['foo|4751|bar1\nfoobar2\nfoo', 'foo|4751|bar6\nfoo']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...