У меня есть длинный текстовый файл со множеством очень похожих строк. Некоторые из них неверны и требуют корректировки.
Пример таких строк:
> 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, мягко говоря, заржавел.
Мысли?
Вы делаете это сложнее, чем должно быть. Просто используйте «аккумулятор» и распечатайте его, когда строка будет завершена.
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
, она эквивалентна коду Тима Робертса, просто абстрагированному (поэтому его можно применить к любой подобной проблеме). По сути, эти два ответа одинаковы.
Предполагая, что первая строка всегда начинается с 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
, чтобы правильно обрабатывать последнюю строку.
Это кажется близким, при первом взгляде не учитывается последняя строка. Я наверняка чему-то научился по этому поводу.
@Натан Спасибо. Я отредактировал его, чтобы правильно обработать последнюю строку.
Вы можете разделить содержимое файла на записи с помощью '\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
Демо здесь
Это работает до сих пор. Фактический файл имеет длину 150 000 строк, поэтому посмотрим, как он с этим справится. В этом коде есть много новых элементов, которые мне предстоит изучить, и я это ценю!