Извлечение данных с использованием регулярных выражений

У меня есть данные в текстовом файле "file.txt"

Рецепты и меню
Советы экспертов
Ингредиенты
Праздники и события
Сообщество
Видео
ЛЕТНЯЯ КУЛИНАРИЯ
Чечевица и Суп из коричневого риса
Gourmet, январь 1991 г.
3,5/4
отзывов (83)
90 %
готовят его снова
Некоторые супы действительно вызывают любовь любить, и это одно из них
. Холодной зимой, когда редакторы Gourmet размышляют о том, какой суп
Приготовить
Отзывы (83)
ВЫХОД: около 14 чашек, порция от 6 до 8
Ингредиенты
5 чашек куриного бульона
1 1/2 чашки чечевицы, перебранной и промытой
1 чашка коричневого риса
банка помидоров весом от 32 до 35 унций, слить воду, сохранить сок и нарезать
3 моркови, разрезать вдоль пополам и нарезать поперек на 1/4-дюймовые кусочки
1 луковицу, нарезать
1 стебель сельдерея, нарезать
3 зубчики чеснока, измельченные
1/2 чайной ложки измельченного сушеного базилика
1/2 чайной ложки измельченного сушеного орегано
1/4 чайной ложки измельченного сушеного тимьяна
1 лавровый лист
1/ 2 стакана измельченных листьев свежей петрушки
2 столовые ложки яблочного уксуса или по вкусу
Приготовление
В сильном чайнике смешайте бульон, 3 стакана воды, чечевицу, рис, помидоры с сохраненным соком,

Я хочу извлечь данные между Ингредиентами и Подготовкой.
Я написал для этого следующее регулярное выражение: -

(?s).*?Ingredients(.*?)Preparation.*

Но он извлекает данные между Ингредиентами, выделенными курсивом, в 3-й строке
файла.txt и Подготовка, но не между данными между Ингредиентами и Подготовка
Какие изменения в моем регулярном выражении следует внести, чтобы решить эту проблему?
Заранее спасибо!


person Akshat Kumar    schedule 10.06.2015    source источник
comment
Какой именно механизм регулярных выражений вы используете?   -  person m0skit0    schedule 10.06.2015


Ответы (4)


Попробуйте сделать свой первый .* жадным. Он съест все Ingredients до последнего перед Preparation:

(?s).*Ingredients(.*?)Preparation.*

Демонстрация: https://regex101.com/r/mQ5eK5/1

person Dmitry Egorov    schedule 10.06.2015

Вы можете использовать ленивый квантификатор .*? со вторым .*:

(?s).*\bIngredients\b(.*?)\bPreparation\b

См. демонстрацию.

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

(?s)\bIngredients\b(?:(?!\b(?:Ingredients|Preparation)\b).)*\bPreparation\b

См. демонстрацию.

person Wiktor Stribiżew    schedule 10.06.2015
comment
Не могли бы вы сообщить мне, что не так с моим ответом? Тот, на который вы переключились, не проверяет границы слов и может соответствовать Preparations, который может быть перед Preparation, и вы получите неправильное подсовпадение. - person Wiktor Stribiżew; 11.06.2015

(?s).*?[*]{2}Ingredients[*]{2}(.*?)[*]{2}Preparation[*]{2}.*

[*]{2}сообщите регулярному выражению, что вам нужен один из символов в списке (здесь один *) дважды {2}.

Я предпочитаю использовать классы символов, чем экранировать, я нашел их более читабельными, чем это:

(?s).*?\*{2}Ingredients\*{2}(.*?)\*{2}Preparation\*{2}.*

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

person Tensibai    schedule 10.06.2015

Вы можете использовать предварительный просмотр, который проверяет, что каждая строка не является Ingredients. Таким образом, вы ограничиваете количество тестов только началом строк (вместо тестирования каждого символа):

(?m)^Ingredients\R((?:(?!Ingredients$).*\R)+?)Preparation$ 

демонстрация

детали узора:

(?m)             # switch on the multiline mode (^ and $ match the limit of the line)
^Ingredients\R   # "Ingredients" at the start of the line followed by a new line
(   # capture group 1
    (?:          # open a non-capturing group
        (?!Ingredients$) # negative lookahead to check that the line is not "Ingredients"
        .*\R             # the line
    )+? # repeat until "Preparation"
)
Preparation$

Примечание: поскольку вы не указали, какой механизм регулярных выражений вы используете, возможно, что \R не поддерживается. В этом случае замените его на \r?\n.

person Casimir et Hippolyte    schedule 10.06.2015