Извлечение подстрок между фигурными скобками внутри строки в массив с помощью PHP

#php #regex

#php #регулярное выражение

Вопрос:

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

Я нашел несколько решений в javascript, но мне это нужно для PHP.

 $string = "www.example.com/?foo={foo}amp;test={test}";
$subStrings = HELPME($string);
print_r($subStrings);
  

Результат должен быть:

 array( [0] => foo, [1] => test )
  

Я попытался поиграть с preg_match, но запутался.

Я был бы признателен, если бы кому-нибудь удалось заставить его работать с preg_match, объясните также, какова логика этого.

Комментарии:

1. В каком контексте вы это делаете?

2. Вы пытаетесь отредактировать шаблон, который будет проанализирован? В противном случае, когда бы вы столкнулись с подобным URL-адресом?

Ответ №1:

Вы можете использовать это регулярное выражение для захвата строк между {}

 {([^}]*)}
  

Объяснение:

  • { Соответствует литералу {
  • ([^}]*) Захватите все символы, отличные от } нуля или более раз. Таким образом, он будет захватывать до следующего } символа.
  • } Соответствует литералу }

Ваш код будет,

 <?php
$regex = '~{([^}]*)}~'; 
$string = "www.example.com/?foo={foo}amp;test={test}";
preg_match_all($regex, $string, $matches);
var_dump($matches[1]);
?>
  

Вывод:

 array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(4) "test"
}
  

ДЕМОНСТРАЦИЯ

Комментарии:

1. Так много ответов, но этот был самым информативным и полезным. Помечено. И спасибо.

Ответ №2:

Шаблон регулярных выражений: {(w )}

Получить все совпадения, которые фиксируются круглыми скобками () . Шаблон говорит, что все, что заключено {...} в, захватывается.

Пример кода:

 $regex = '/{(w{1,})}/';
$testString = ''; // Fill this in
preg_match_all($regex, $testString, $matches);
// the $matches variable contains the list of matches
  

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


Если вы хотите захватить любой тип символа внутри {...} , попробуйте использовать приведенный ниже шаблон регулярных выражений.

Регулярное выражение : {(.*?)}

Пример кода:

 $regex = '/{(.{0,}?)}/';
$testString = ''; // Fill this in
preg_match_all($regex, $testString, $matches);
// the $matches variable contains the list of matches
  

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

Комментарии:

1. Этот debuggex потрясающий! Спасибо за вашу помощь.

2. Вам не нужно использовать двойные обратные косые черты в PHP. (в качестве комментария, в данном случае вам вообще не нужны обратные ссылки)

3. @CasimiretHippolyte Я не имею ни малейшего представления о PHP, а код скопирован из debuggex, и он работает. Позвольте мне обновить свой пост.

4. Если вы хотите, вы можете попробовать что-то вроде regex101.com это создает более совместимый с PHP код. (однако использование двойной обратной косой черты не является проблемой, код работает, он только бесполезен)

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

Ответ №3:

 <?php
$string = "www.example.com/?foo={foo}amp;test={test}";
$found = preg_match('/{([^}]*)}/',$string, $subStrings);
if($found){
   print_r($subStrings);
}else{
    echo 'NOPE !!';
}
  

ДЕМОНСТРАЦИЯ ЗДЕСЬ

Ответ №4:

Функция parse_url, которая анализирует URL-адрес и возвращает его компоненты. Включая строку запроса.

Комментарии:

1. Это неплохая идея, но она охватывает только первый шаг (извлечение значений). Однако после использования parse_url вы должны определить для каждого значения, начинается ли оно и заканчивается фигурными скобками, и вы должны удалить их, чтобы получить результат.

2. вы можете использовать это решение : $query= $_SERVER['QUERY_STRING']; parse_str($query,$out); var_dump($out);

Ответ №5:

Попробуйте это:

 preg_match_all("/{.*?}/", $string, $subStrings);
var_dump($subStrings[0]);
  

Удачи!

Ответ №6:

Вы можете использовать выражение (?<={).*?(?=}) для сопоставления любой строки текста, заключенной в {} .

 $string = "www.example.com/?foo={foo}amp;test={test}";
preg_match_all("/(?<={).*?(?=})/",$string,$matches);
print_r($matches[0]);
  

Объясненное регулярное выражение:

(?<={) это положительный взгляд назад, утверждающий, что строке текста предшествует a { . Аналогично (?=}) , положительный прогноз утверждает, что за ним следует a } . .* соответствует 0 или более символам любого типа. И ? in .*? позволяет ему соответствовать наименьшему возможному количеству символов. (Это означает, что он соответствует foo в {foo} and {bar} , а не foo} and {bar .

$matches[0] содержит массив всех совпадающих строк.

Ответ №7:

Я вижу ответы здесь, используя регулярные выражения с группами захвата, поисковыми системами и отложенными кванторами. Все эти методы замедляют работу шаблона — конечно, производительность вряд ли будет заметна в большинстве случаев использования. Поскольку мы призваны предлагать решения, подходящие для большего количества сценариев, чем просто опубликованный вопрос, я предложу несколько решений, которые обеспечивают ожидаемый результат и объясняют различия, используя строку OP www.example.com/?foo={foo}amp;test={test} , присвоенную $url . Я подготовил php-демонстрацию методов, которым нужно следовать. Для получения информации о вызовах функций, пожалуйста, перейдите по ссылкам на руководство по php. Для углубленной разбивки шаблонов регулярных выражений я рекомендую использовать regex101.com — бесплатный онлайн-инструмент, который позволяет вам тестировать шаблоны по строкам, видеть результаты как в виде выделенного текста, так и в виде сгруппированного списка, а также предоставляет методику разбивки по символам того, как механизм регулярных выражений интерпретирует ваш шаблон.


#1 Поскольку ваша входная строка представляет собой URL-адрес, подходит метод, не основанный на регулярных выражениях, поскольку в php есть собственные функции для его анализа: parse_url() с parse_str() . К сожалению, ваши требования выходят за рамки извлечения значений строки запроса, вы также хотите переиндексировать массив и удалить фигурные скобки из значений.

 parse_str(parse_url($url, PHP_URL_QUERY), $assocArray);
$values = array_map(function($v) {return trim($v, '{}');}, array_values($assocArray));
var_export($values);
  

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


#2 preg_match_all() — это очень краткий и высокоэффективный метод извлечения значений. Одним из недостатков использования регулярных выражений является то, что механизм регулярных выражений полностью «не знает» о каких-либо специальных значениях, которые может иметь форматированная входная строка. В этом случае я не вижу никаких негативных последствий, но когда возникают сбои, часто решением является использование синтаксического анализатора, который «поддерживает формат / тип данных».

 var_export(preg_match_all('~{K[^}]*~', $url, $matches) ? $matches[0] : []);
  

Обратите внимание, что моему шаблону не нужны группы захвата или поисковые запросы; и мой ответ не страдает от использования отложенного квантификатора. K используется для «перезапуска соответствия полной строки» (другими словами, забыть все совпадающие символы до этого момента). Все эти функции будут означать, что механизм регулярных выражений может обрабатывать строку с максимальной эффективностью. Если есть недостатки в использовании функции, они:

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

#3 preg_split() наиболее точно соответствует простой английской цели вашей задачи И предоставляет точный вывод в качестве возвращаемого значения.

 var_export(preg_split('~(?:(?:^|})[^{]*{)|}[^{]*$~', $url, 0, PREG_SPLIT_NO_EMPTY));
  

Мой шаблон, по общему признанию, неприятный для начинающего дизайнера шаблонов регулярных выражений и немного менее эффективный, поскольку он создает «разветвленные» совпадения ( | ), в основном гласит: «Разделите строку на следующие разделители:

  • из начала строки или из a } , включая все { несимволы, затем первый встреченный { (это конец разделителя).
  • начиная с конца } , включая все { несимволы до конца строки.»