Regex для сбора данных после одного поискового запроса и перед одним из двух других (который всегда первый)

Мне нужно создать регулярное выражение со следующими требованиями:

Данный образец текста:

SEARCH_TERM_#1 find this text SEARCH-TERM_#2_more text_SEARCH-TERM_#3
SEARCH_TERM_#1 find this text SEARCH-TERM_#3

Я хочу извлечь строку, которая появляется в find this text площадь

Регулярное выражение должно собирать данные после SEARCH_TERM_#1 до, но не включая SEARCH_TERM_#2 или же SEARCH-TERM_#3 что наступит раньше. Он должен выбрать в качестве "правой стороны" границы поиска то, что он найдет первым из #2 и #3.

я пробовал (?>SEARCH_TERM_#2|SEARCH_TERM_#3)(?=(?>SEARCH_TERM_#2|SEARCH_TERM_#3)) а также (?>(?=SEARCH_TERM_#2)|(?=SEARCH_TERM_#3)), И они ВСЕ включают второй поисковый термин в собранные данные и останавливаются перед третьими, в то время как я хочу, чтобы собранные данные останавливались перед № 2 или № 3, который когда-либо будет первым.

2 ответа

Решение

Описание

Это регулярное выражение будет:

  • найти первый SEARCH_TERM_#1
  • захватить текст, начинающийся после SEARCH_TERM_#1
  • прекратить захват текста, когда он сталкивается либо SEARCH_TERM_#2 или же SEARCH_TERM_#3 (который когда-либо первый

^.*?SEARCH_TERM_\#1((?:(?!SEARCH-TERM_\#2|SEARCH-TERM_\#3).)*)

введите описание изображения здесь

расширенный

  • ^ соответствует началу строки, это заставляет поиск начинаться с начала
  • .*? сопоставьте все символы до следующего выражения. обратите внимание, что этот термин должен использоваться в сочетании с s опция, которая позволяет точке соответствовать символам новой строки
  • SEARCH_TERM_\#1 первый поисковый термин
  • ( запустить группу захвата этот набор скобок помещает соответствующие значения в группу захвата 1
  • (?: начать не захватывать группу, это настоящая магия, и в основном позволяет содержанию выражения продолжать сопоставление, пока не наткнется на SEARCH-TERM_\#2 или же SEARCH-TERM_\#3
    • (?! начать негативный взгляд. Подумайте о движке регулярных выражений, который перемещает курсор по входной строке. Loohahead просто смотрит на символы после курсора, не перемещая курсор. Отрицательное значение означает, что если найденное выражение разрешается как совпадающее, то запрещает совпадение или, если выражение не найдено, разрешает совпадение.
    • SEARCH-TERM_\#2|SEARCH-TERM_\#3 ищите любое значение. | является оператором "или"
    • ) закрыть негативный взгляд
    • . соответствовать любому персонажу. Выражение попадает в это место только в том случае, если предыдущий отрицательный взгляд не нашел его условий поиска.
    • ) закройте группу без захвата, на этом этапе либо поиск остановлен, так как он обнаружил конечное условие #2 или #3, либо группа без захвата нашла один символ
  • * продолжить жадно сопоставляя все символы. Вы можете использовать жадность, потому что конечное условие содержится внутри выражения.
  • ) закрыть группу захвата

    Пример кода PHP

Вы не указали язык, поэтому я включил этот пример PHP только для того, чтобы показать, как он работает.

Ввод текста

skip this text SEARCH_TERM_#1 find this text SEARCH-TERM_#2 more text to ignore SEARCH_TERM_#3

Код

<?php
$sourcestring="your source string";
preg_match('/^.*?SEARCH_TERM_\#1((?:(?!SEARCH-TERM_\#2|SEARCH-TERM_\#3).)*)/ims',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>

Матчи

$matches Array:
(
    [0] => skip this text SEARCH_TERM_#1 find this text 
    [1] =>  find this text 
)

Пример из реального мира

Или использовать пример из реального мира, включенный в комментарии:

Regex: ^.*?style="background-image: url\(((?:(?!&cfs=1|\)).)*)

Введите текст: <a href=http://i.like.kittens.com style="background-image: url(http://I.like.kittens.com?Name=Boots&cfs=1)">

Матчи:

[0] => <a href=http://i.like.kittens.com style="background-image: url(http://I.like.kittens.com?Name=Boots
[1] => http://I.like.kittens.com?Name=Boots

отказ

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

Этот шаблон хорошо работает:

SEARCH_TERM_#1(.*?)SEARCH-TERM_#2_OR_#3

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

Если поддерживается, вы можете использовать loo karounds:

(?<=SEARCH_TERM_#1).*?(?=SEARCH-TERM_#2_OR_#3)

Тогда результатом является весь шаблон.

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

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