В регулярном выражении вы можете «захватить» части согласованной строки с помощью (brackets)
; в этом случае вы захватываете (^|_)
и ([a-z])
части матча. Они нумеруются начиная с 1, поэтому у вас есть обратные ссылки 1 и 2. Матч 0 - это вся строка с согласованием.
Модификатор /e
принимает заменяющую строку и заменяет обратную косую черту с последующим номером ( например, \1
) с соответствующей обратной ссылкой, но поскольку вы находитесь внутри строки, вам нужно избежать обратной косой черты, чтобы вы получили '\\1'
. Затем он (эффективно) запускает eval
, чтобы запустить результирующую строку, как если бы это был PHP-код (поэтому он устарел, потому что его легко использовать eval
небезопасным способом).
Функция preg_replace_callback
вместо этого выполняет функцию обратного вызова и передает ей массив, содержащий совпадающие обратные ссылки. Итак, где бы вы написали '\\1'
, вместо этого вы получите доступ к элементу 1 этого параметра - например. если у вас есть анонимная функция формы function($matches) { ... }
, первая обратная ссылка - $matches[1]
внутри этой функции.
Итак, аргумент /e
в
'do_stuff(\\1) . "and" . do_stuff(\\2)'
может стать обратным вызовом
function($m) { return do_stuff($m[1]) . "and" . do_stuff($m[2]); }
. Или в вашем случае
'strtoupper("\\2")'
может стать
function($m) { return strtoupper($m[2]); }
Обратите внимание, что $m
и $matches
не являются волшебными именами, это просто имя параметра, которое я дал при объявлении моих функций обратного вызова. Кроме того, вам не нужно передавать анонимную функцию, это может быть имя функции в виде строки или что-то вроде формы array($object, $method)
, как с любым обратным вызовом в PHP , например
function stuffy_callback($things) {
return do_stuff($things[1]) . "and" . do_stuff($things[2]);
}
$foo = preg_replace_callback('/([a-z]+) and ([a-z]+)/', 'stuffy_callback', 'fish and chips');
Как и в любой функции, вы не можете получить доступ к переменным вне вашего обратного вызова (из окружения) по умолчанию. При использовании анонимной функции вы можете использовать ключевое слово use
для импорта переменных, которые вам нужны для доступа, , как описано в руководстве по PHP . например если старый аргумент был
'do_stuff(\\1, $foo)'
, тогда новый обратный вызов может выглядеть как
function($m) use ($foo) { return do_stuff($m[1], $foo); }
preg_replace_callback
- вместо модификатора /e
в регулярном выражении, поэтому вам нужно удалить этот флаг из вашего аргумента «pattern». Таким образом, шаблон, подобный /blah(.*)blah/mei
, станет /blah(.*)blah/mi
. /e
использовал внутри аргумента addslashes()
вариант, поэтому некоторые замены использовали stripslashes()
для его удаления; в большинстве случаев вы, вероятно, хотите удалить вызов stripslashes
из вашего нового обратного вызова. После того как Вы сделали это, у Вас на самом деле будет разумная идея проблемы/решения.
Прямо сейчас у Вас просто есть теории, плавающие вокруг в Вашей голове, большинство которых окажется дезинформированным.
Шаг 3: Осуществите рефакторинг беспощадно. Ваша цель должна состоять в том, чтобы удалить приблизительно половину Вашего кода
Вы найдете, что Ваш код в конце или напомнит существующий шаблон разработки, или Вы создадите новый. Вы будете затем квалифицированы для ответа на этот вопрос :-)
Стратегическая модель, возможно, один, Вы хотите посмотреть на. Причем стратегия является алгоритмом парсинга файла.
Затем Вы хотите отдельную стратегию вставки базы данных.
Я полностью соглашаюсь с Orion Edwards, и это обычно - способ, которым я приближаюсь к проблеме; но в последнее время я начинал видеть некоторые шаблоны (!) к безумию.
Для более сложных задач я обычно использую что-то как интерпретатор (или стратегия), который использует некоторого разработчика (или фабрика) для создания каждой части данных.
Для потоковой передачи данных весь синтаксический анализатор посмотрел бы что-то как адаптер, адаптирующийся от потокового объекта до объектного потока (который обычно является просто очередью).
Для Вашего примера, вероятно, был бы один разработчик для полной структуры данных (от главы к EOF), который внутренне использует разработчиков для внутренних элементов данных (питаемый интерпретатором). После того как с EOF встречаются, объект был бы испущен.
Однако объекты, созданные в операторе переключения в некоторой функции фабрики, являются, вероятно, самым простым путем ко многим меньшим задачам. Кроме того, мне нравится сохранять мои объекты данных неизменными, поскольку Вы никогда не знаете, когда кто-то пихает параллелизм вниз Ваше горло :)
Используйте Закон и YACC. Если Вы не посвятите следующие десять лет исключительно этому предмету, они произведут лучше и более быстрый код каждый раз.