Возникли проблемы с удвоением с двумя регулярными выражениями

У меня есть рабочий проект, я пытаюсь написать код Python для автоматизации набора данных, который мне нужен ежемесячно. У меня есть примерно 300-400 разных записей в случайном текстовом файле. У меня нет возможности изменить то, как данные поступают ко мне каждый месяц, но мне нужно вытащить примерно половину из них в отдельный текстовый файл, чтобы передать другому человеку. Раньше мы разбивали их вручную, но мне бы очень хотелось автоматизировать этот процесс. Я очень новичок в python и надеюсь научиться в процессе создания этого скрипта.

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

pattern = re.compile('^START[\S\s]*END$',re.MULTILINE)

ccgjju = re.compile('WNO/CC[\S\s]',re.MULTILINE)

filetowrite = 'ccgjju.txt'

tempFile = open(filetowrite, 'a' )

for pattern in open('source.txt'):

    if ccgjju.match(pattern):

        tempFile.write(pattern)

tempFile.close()

Мой исходный файл содержит 300-500 записей, подобных этому

START
NAME/SMITH,JOHN SEX/M RAC/W
MIS/RANDOM INFORMATION
WNO/CC124589 DAT/01012019
ADDR/121 MAIN ST
END

START
NAME/THOMPSON,JOHN SEX/M RAC/W
MIS/RANDOM INFORMATION
WNO/DC0123456 DAT/01012019
ADDR/121 MAIN ST
END

START
NAME/THOMAS,JOHN SEX/M RAC/W
MIS/RANDOM INFORMATION
WNO/CC01234 DAT/01012019
ADDR/121 MAIN ST
END

Я хочу, чтобы он вытягивал все между START и END, если в строке WNO/CC есть WNO/CC вместо WNO/DC. В настоящее время он возвращает в выходной файл следующее, а не всю запись между ними.

WNO/CC124589 DAT/01012019
WNO/CC01234 DAT/01012019
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вы читаете строку за строкой, вы не найдете совпадения. Пытаться:

with open('source.txt') as f:
    s = f.read()

# get the blocks between START and END
blocks = re.findall(r'START([\s\S]*?)END', s, re.M)

# same as
blocks = re.findall(r'START(.*?)END', s, re.M|re.S)

# get the blocks that match WNO/CC
res = [b for b in blocks if re.findall(r'WNO/CC', b)]

Используйте *?, чтобы получить кратчайшее совпадение вместо жадного совпадения.

Вы можете использовать . вместо [\s\S], если добавите re.DOTALL к флагам. Кроме того, вы можете комбинировать регулярные выражения, не нужно делать это в два этапа.

Blorgbeard 09.04.2019 05:56

@Blorgbeard Хороший улов. Я улучшу его.

knh190 09.04.2019 05:58

Это решило мою проблему. Теперь я могу получить весь текст между началом и концом. То, что обычно занимает 3-4 часа в месяц, я думаю, что могу уложиться в 10 минут. Это потрясающе.

Tkmelz 09.04.2019 06:19

@Tkmelz Не за что. Однако я не смог правильно совместить регулярное выражение, может быть, кто-то другой мог бы это исправить ;) Но для случая с 300-400 блоками это нормально.

knh190 09.04.2019 06:22

Я упростил свою проблему. У меня есть около 8 различных фрагментов текста, которые можно найти внутри блоков. и каждая из этих частей будет определять, в какой из 6 файлов они входят. Я думаю, что сейчас максимум, что я получаю каждый месяц, это 540 записей, но это определенно направит меня в правильном направлении. На самом деле я уже запускал его на большом файле, и он работал отлично. Теперь только изменить его, чтобы вытащить остальные из них в отдельные файлы.

Tkmelz 09.04.2019 06:25

Я имел в виду что-то вроде re.findall(r'START(?:(?!END).)*WNO/CC.*?END', s, re.M | re.S) (код), но да, было сложно убедиться, что он не потребляет несколько блоков. Два шага тоже хорошо, и их легче читать.

Blorgbeard 10.04.2019 01:41

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