#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
}
, включая все{
несимволы, затем первый встреченный{
(это конец разделителя). - начиная с конца
}
, включая все{
несимволы до конца строки.»