Как сопоставить текст и необязательные повторяющиеся идентификаторы и сгруппировать их вместе?

avatar
Daniel
8 августа 2021 в 22:44
102
1
3

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

Вот несколько фиктивных данных:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 EX 0-02a
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Vestibulum eget vestibulum sapien.
Sed porta, odio id sollicitudin congue
          EX 0-04a

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Vestibulum eget vestibulum sapien, sed porta, odio id sollicitudin congue
Lorem ipsum dolor sit amet
EX 0-01a / EX 0-05a / EX 0-07a /
EX 0-08a


Lorem ipsum dolor sit amet, 
consectetur adipiscing 
elit.
Vestibulum eget 
vestibulum sapien.
                                                      EX 3-11b

На данный момент я создал это регулярное выражение:

(.*?)(\w{2,4} \d-\d{0,2}\w)

Это успешно захватывает текст и один единственный код, но некоторые блоки имеют несколько кодов (иногда в нескольких строках), и они не сгруппированы вместе, так как / подбираются как совпадения.

Вот какой вывод мне нужен:

[(Lorem ipsum dolor sit amet, consectetur adipiscing elit.), (EX 0-01a / EX 0-02a / EX 0-05b / EX 0-03a)]

Regex101: https://regex101.com/r/Wfc4nj/1

Источник
FMc
8 августа 2021 в 23:24
1

В данных, как показано, вам вообще не нужно регулярное выражение. (1) Разбейте текст на абзацы: это можно сделать либо с помощью text.split('\n\n'), либо путем повторения строки за строкой и использования пустых строк для организации данных. (2) В каждом абзаце отделите первую строку (текст) от остальных (коды, которые вы хотите зафиксировать). (3) Разделите строки с кодами, используя line.split('/'), и удалите ненужные пробелы, используя strip(). Если фактические данные более сложны, вы должны предоставить более подробный пример, чтобы продемонстрировать ситуацию.

Daniel
9 августа 2021 в 00:53
0

@FMc - как вы упомянули, данные не совсем так структурированы, как в примере, они содержат несколько разрывов строк по всему тексту (это извлекается из файла Word), и нет гарантии, что разрыв строки разделит данные построчно. Я обновил вопрос, чтобы отразить это.

Xitiz
9 августа 2021 в 02:27
0

Почему пример изменен, но Это тот тип вывода, который мне нужен: не изменен? И вы также не предоставили то, что пробовали на питоне!

Ответы (1)

avatar
The fourth bird
9 августа 2021 в 06:24
1

Вы можете повторить шаблон, соответствующий идентификатору в группе захвата, и использовать \s+ для сопоставления 1 или более пробельных символов, которые также соответствуют новой строке, если идентификаторы могут находиться в нескольких строках.

\s*(.+?)\s*(\w{2,4} \d-\d{0,2}\w(?:\s+/\s+\w{2,4} \d-\d{0,2}\w)*)

См. демонстрацию регулярного выражения и демонстрацию Python.

Например

import re

pattern = r"\s*(.+?)\s*(\w{2,4} \d-\d{0,2}\w(?:\s+/\s+\w{2,4} \d-\d{0,2}\w)*)"

s = ("Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
            " EX 0-02a\n"
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
            "Vestibulum eget vestibulum sapien.\n"
            "Sed porta, odio id sollicitudin congue\n"
            "          EX 0-04a\n\n"
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
            "Vestibulum eget vestibulum sapien, sed porta, odio id sollicitudin congue\n"
            "Lorem ipsum dolor sit amet\n"
            "EX 0-01a / EX 0-05a / EX 0-07a /\n"
            "EX 0-08a\n\n\n"
            "Lorem ipsum dolor sit amet, \n"
            "consectetur adipiscing \n"
            "elit.\n"
            "Vestibulum eget \n"
            "vestibulum sapien.\n"
            "                                                      EX 3-11b")

print(re.findall(pattern, s, re.S))

Вывод

[
('Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 'EX 0-02a'),
('Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nVestibulum eget vestibulum sapien.\nSed porta, odio id sollicitudin congue', 'EX 0-04a'),
('Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nVestibulum eget vestibulum sapien, sed porta, odio id sollicitudin congue\nLorem ipsum dolor sit amet', 'EX 0-01a / EX 0-05a / EX 0-07a /\nEX 0-08a'), 
('Lorem ipsum dolor sit amet, \nconsectetur adipiscing \nelit.\nVestibulum eget \nvestibulum sapien.', 'EX 3-11b')
]
Daniel
12 августа 2021 в 14:10
1

Ницца! Это делает именно то, что мне нужно. Спасибо.