Перебирать список строк до тех пор, пока строка == новая строка

Я пытаюсь прочитать выборочную информацию из файла. Структура файла следующая:

Component1:
   Detail1
   Detail2
   Detail3

Component2:
   Detail1
   Detail2
   Detail3

Component3:
   Detail1
   Detail2
   Detail3

Component4:
   Detail1
   Detail2
   Detail3

Файл имеет ограниченный номер. строк, и я читаю этот файл в список строк.

with open('/tmp/filename.txt', 'r') as openf:
            for line_no, line in enumerate(openf):
                file_lines_list.append(line)

Я хочу выборочно прочитать информацию Компонент2

Поэтому я написал следующий код.

with open('/tmp/filename.txt', 'r') as f:
                for line_no, line in enumerate(f):
                    if "Component2" in line:
                       x = line_no
                       print(x)
                       for item in file_lines_list[x:]:
                           if item != "\n":   
                              tmp_file.write(item)
                           else:
                              break

Но он печатает строки до конца списка (строк файла). Он не прерывается при первом появлении новой строки, которая в идеале должна быть строкой непосредственно перед Компонент3. (Нет новых строк между деталями компонентов) Может ли кто-нибудь указать, что я здесь делаю неправильно?

Использовать startswith() и разбивать на пустую строку?

DirtyBit 10.04.2019 17:27
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
323
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Использование str.startswith() вместе с логическим флагом:

список.txt:

Component1:
   C1_Detail1
   C1_Detail2
   C1_Detail3

Component2:
   C2_Detail1
   C2_Detail2
   C2_Detail3

Component3:
   C3_Detail1
   C3_Detail2
   C3_Detail3

Component4:
   C4_Detail1
   C4_Detail2
   C4_Detail3

Следовательно:

with open('list.txt', 'r') as f:
    content = f.readlines()

# you may also want to remove empty lines
content = [l.strip() for l in content if l.strip()]
bFlag = False
for line in content:
    if line.startswith('Component2'):
        bFlag = not bFlag
    if bFlag:
        if 'Component3' in line:
            break
        else:
            print(line)

ВЫХОД:

Component2:
C2_Detail1
C2_Detail2
C2_Detail3
with open('file') as file:
    # remove empty lines
    lines = [line for line in file.readlines() if line]

    # holds all our components
    components = {}
    # holds the last component
    comp_name = None
    for line in lines:
        if not line.startswith('   '):
            # remove : from the end for easy reference
            comp_name = line[:-1]
            # add new Component our map
            components[comp_name] = []
        else:
            # add detail to component that already exists
            components[comp_name].append(line.strip())

    # now we just find our component
    print(components['Component2'])

Это печатает:

['Detail1', 'Detail2', 'Detail3']

Не уверен, что чтение всех данных в память только для последующей фильтрации эффективно.

DirtyBit 10.04.2019 17:47
readlines прочитает весь файл в память, несмотря ни на что. Если вы хотите быть эффективным, вы можете передать файл в потоковом режиме, но это не вопрос.
JBirdVegas 10.04.2019 17:51
Ответ принят как подходящий

Для меня эта задача упрощается, если вы загружаете текст целиком (используя read), а не как список строк (используя readlines). Я бы сделал это следующим образом:

with open('input_file.txt','r') as openf:
    data = openf.read()
components = data.split('\n\n')
components = [i for i in components if i.startswith('Component2')]
print(len(components)) #prints 1 as expected
with open('out_file.txt','w') as f:
    f.write(components[0])

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

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