Манипулирование строками с использованием строк чтения и организация результатов на основе следующей строки

У меня есть длинный текстовый файл со множеством очень похожих строк. Некоторые из них неверны и требуют корректировки.

Пример таких строк:

> set device-group PA7050-T4-EXTRANET description "Contact: Engineering
> Permit test sharepoint server web access"
> set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB
> set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB 
> lots of stuff to add her
> a few lines here.
> set device-group PA7050-T4-EXTRANET pre-rulebase security rules

Цель состоит в том, чтобы гарантировать, что каждая строка начинается с set... и если это не так, это означает, что она принадлежит к заданной строке самой последней строки.

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

skip_line = False
c = 0

with open("test.txt", 'r') as f:
lines = f.readlines()



for i in range(0, len(lines)):
    if skip_line:
        if i+c < len(lines):
            i+=c
    set_line = lines[i].rstrip()
    skip_line - False
    for j in range(i+1, len(lines)):
        while not lines[j].startswith("set"):
            set_line = set_line + lines[j].rstrip()
            c+=1
            j+=1
            skip_line = True
    print(set_line)

это должен быть результат:

set device-group PA7050-T4-EXTRANET  description "Contact: EngineeringPermit test sharepoint server web access"
set device-group PA7050-T4-EXTRANET4-SPTST-TO-WEB group-tag MigratedFromT4
set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB source-hip anylots of stuff to add herea few lines here.
set device-group PA7050-T4-EXTRANET pre-rulebase security rules T4-SPTST-TO-WEB source-hip any

но я получаю много смешанных результатов. Некоторые из них верны, а иногда это просто повторяется.

Как лучше это разобрать и почистить. КАЖДАЯ строка должна начинаться с «Set»... все остальное должно быть возвращено в самую последнюю строку «Set».

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

Мысли?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
50
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

data = """\
set device-group PA7050-T4-EXTRANET  description "Contact: Engineering
Permit test sharepoint server web access
set device-group PA7050-T4-EXTRANET4-SPTST-TO-WEB group-tag MigratedFromT4
set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB source-hip any
lots of stuff to add here
a few lines here.
set device-group PA7050-T4-EXTRANET pre-rulebase security rules T4-SPTST-TO-WEB source-hip any"""


gather = ''
for line in data.splitlines():
    if line.startswith('set'):
        if gather:
            print(gather)
        gather = line
    else:
        gather += ' '+line
if gather:
    print(gather)
Ответ принят как подходящий

Самый простой способ сделать это — использовать Ruby slice_before, чтобы разрезать список на нужные фрагменты, а затем соединить каждый фрагмент вместе. К сожалению, в Python его нет.

Так что нам просто нужно будет это написать.

def slice_before(iterable, predicate):
    iterator = iter(iterable)
    try:
        prev_item = next(iterator)
    except StopIteration:
        return
    
    group = [prev_item]

    for item in iterator:
        if predicate(item):
            yield group
            group = []
        group.append(item)
    
    if group:
        yield group

При этом проблема тривиальна:

with open("test.txt", 'r') as f:
    lines = f.readlines()

fixed_lines = [
    ' '.join(part.strip() for part in chunk)
    for chunk in slice_before(lines, lambda line: line.startswith('set '))
]

for line in fixed_lines:
    print(line)
# => set device-group PA7050-T4-EXTRANET  description "Contact: Engineering  Permit test sharepoint server web access
#    set device-group PA7050-T4-EXTRANET4-SPTST-TO-WEB group-tag MigratedFromT4
#    set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB source-hip any  lots of stuff to add here  a few lines here.
#    set device-group PA7050-T4-EXTRANET pre-rulebase security rules T4-SPTST-TO-WEB source-hip any

Обновлено: Если вы посмотрите на структуру slice_before, она эквивалентна коду Тима Робертса, просто абстрагированному (поэтому его можно применить к любой подобной проблеме). По сути, эти два ответа одинаковы.

Это работает до сих пор. Фактический файл имеет длину 150 000 строк, поэтому посмотрим, как он с этим справится. В этом коде есть много новых элементов, которые мне предстоит изучить, и я это ценю!

Nathan 13.08.2024 14:58

Предполагая, что первая строка всегда начинается с set , вы можете написать что-то вроде:

with open("test.txt", 'r') as f:
    lines = f.readlines()

c = lines[0].rstrip()
for l in lines[1:]:
    l = l.rstrip()
    if not l.startswith('set '):
        c += l
    else:
        print(c)
        c = l
print(c)

UPD: Добавлен print, чтобы правильно обрабатывать последнюю строку.

Это кажется близким, при первом взгляде не учитывается последняя строка. Я наверняка чему-то научился по этому поводу.

Nathan 13.08.2024 14:26

@Натан Спасибо. Я отредактировал его, чтобы правильно обработать последнюю строку.

Yuri Ginsburg 13.08.2024 23:56

Вы можете разделить содержимое файла на записи с помощью '\nset ', а для каждой записи разделить строки и соединить их пустой строкой, а затем снова объединить записи в строку с помощью '\nset ':

# data = f.read() in your actual code
data = """\
set device-group PA7050-T4-EXTRANET  description "Contact: Engineering
Permit test sharepoint server web access"
set device-group PA7050-T4-EXTRANET4-SPTST-TO-WEB group-tag MigratedFromT4
set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB source-hip any
lots of stuff to add here
a few lines here.
set device-group PA7050-T4-EXTRANET pre-rulebase security rules T4-SPTST-TO-WEB source-hip any"""

print('\nset '.join(''.join(record.splitlines()) for record in data.split('\nset ')))

Это выводит:

set device-group PA7050-T4-EXTRANET  description "Contact: EngineeringPermit test sharepoint server web access"
set device-group PA7050-T4-EXTRANET4-SPTST-TO-WEB group-tag MigratedFromT4
set device-group PA7050-T4-EXTRANE T4-SPTST-TO-WEB source-hip anylots of stuff to add herea few lines here.
set device-group PA7050-T4-EXTRANET pre-rulebase security rules T4-SPTST-TO-WEB source-hip any

Демо здесь

Другие вопросы по теме