Как я могу получить три параметра из строки, используя preg_match_all?

Я пытаюсь получить из текста все вхождения фрагмента кода и 3 параметра. Я делаю это с помощью функций PHP регулярное выражение и preg_match_all.

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

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

Функция

public function getGallerySnippetOccurrences($text) {

    $ptn = '/{# +gallery +(src|width|height)=\[(.*)\] +(src|width|height)=\[(.*)\] +(src|width|height)=\[(.*)\] +#}/';

    if (preg_match_all($ptn,$text,$matches)){
        $turnedMatches = $this->turn_array($matches);
        return $turnedMatches;
    }
    else {
        return null;
    }
}

Текст 1 (в данном случае работает как аспектированный)

Lorem ipsum {# gallery src=[holiday_images/london] width=[400] height=[300] #} sid amet.

Возвращает:

array(1) {
  [0] =>
  array(7) {
    [0] =>
    string(66) "{# gallery src=[holiday_images/london] width=[400] height=[300] #}"
    [1] =>
    string(3) "src"
    [2] =>
    string(21) "holiday_images/london"
    [3] =>
    string(5) "width"
    [4] =>
    string(3) "400"
    [5] =>
    string(6) "height"
    [6] =>
    string(3) "300"
  }
}

Текст 2 (неконтролируемое поведение)

Lorem ipsum {# gallery src=[holiday_images/london] width=[400] height=[300] #} sid amet {# gallery src=[holiday_images/paris] width=[400] height=[300] #}

Возвращает

array(1) {
  [0] =>
  array(7) {
    [0] =>
    string(141) "{# gallery src=[holiday_images/london] width=[400] height=[300] #} sid amet {# gallery src=[holiday_images/paris] width=[400] height=[300] #}"
    [1] =>
    string(3) "src"
    [2] =>
    string(96) "holiday_images/london] width=[400] height=[300] #} sid amet {# gallery src=[holiday_images/paris"
    [3] =>
    string(5) "width"
    [4] =>
    string(3) "400"
    [5] =>
    string(6) "height"
    [6] =>
    string(3) "300"
  }
}

Что я делаю неправильно?

Сделайте это не жадным: /{# +gallery +(src|width|height)=\[(.*?)] +(src|width|height)=\[(.*?)] +(src|width|height)=\[(.*?)] +#}/

anubhava 13.03.2019 18:13

смотри мой ответ ниже

Rinsad Ahmed 13.03.2019 18:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
2
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В вашем шаблоне вы используете жадные совпадения, используя (.), который следует заменить нежадным шаблоном (.?). Пожалуйста, найдите образец ниже

$ptn = '/{# +gallery +(src|width|height)=\[(.*?)\] +(src|width|height)=\[(.*?)\] +(src|width|height)=\[(.*?)\] +#}/';
Ответ принят как подходящий

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

Вы можете рассмотреть этот подход для обеих точек:

$re = '/{\#
\h+gallery
\h+(src|width|height)=\[([^]]*)]
\h+((?1))=\[([^]]*)]
\h+((?1))=\[([^]]*)]
\h*\#}/x';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

// Print the entire match result
var_dump($matches); 

Демонстрация регулярных выражений

  • Обратите внимание, как это регулярное выражение определяет подшаблон и повторно использует его во всем регулярном выражении, используя (?1), чтобы избежать повторений.
  • Также обратите внимание на использование более эффективного инвертированного класса [^]]* вместо неэффективного .*? для захвата значений.

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