Замена тегов на Includes в PHP регулярными выражениями

StackOverflow https://stackoverflow.com/questions/723188

Вопрос

Мне нужно прочитать строку, определить {VAR}, а затем выполнить file_get_contents('VAR.php ') вместо {VAR}."VAR" может называться как угодно, например TEST, или CONTACT-FORM, и т.д.Я не хочу знать, что такое VAR - не для того, чтобы выполнять жестко запрограммированное условие, а для того, чтобы просто увидеть заглавный буквенно-цифровой тег, окруженный фигурными скобками, и просто выполнить file_get_contents(), чтобы загрузить его.

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

Чем это полезно?Это полезно при подключении WordPress.

Это было полезно?

Решение

У Orion выше есть правильное решение, но на самом деле нет необходимости использовать функцию обратного вызова в вашем простом случае.

Предполагая, что имена файлов - это A-Z + дефисы, вы можете сделать это в 1 строке, используя флаг PHP / e в регулярном выражении:

$str = preg_replace('/{([-A-Z]+)}/e', 'file_get_contents(\'$1.html\')', $str);

Это заменит любой экземпляр {VAR} содержимым VAR.html .Вы могли бы добавить префикс пути ко второму члену, если вам нужно указать конкретный каталог.

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

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

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

  1. Во-первых, вам нужно, чтобы регулярное выражение соответствовало правильно.Это должно быть довольно легко с чем-то вроде /{\w+}/.

  2. Далее вам нужно будет использовать все флаги для preg_match, чтобы получить местоположение смещения в данных страницы.Это смещение позволит вам разделить строку на части "до", "совпадение" и "после" совпадения.

  3. Как только у вас будут 3 части, вам нужно будет запустить include и склеить их обратно вместе.

  4. Вспеньте, смойте, повторите.

  5. Остановитесь, когда вы больше не найдете переменных.

Это не очень эффективно, и, вероятно, есть способы получше.Возможно, вы захотите вместо этого рассмотреть возможность выполнения preg_split, разделив на /[{}]/.Независимо от того, как вы его разделяете, вы предполагаете, что можете доверять своим входящим данным, и это значительно упростит весь процесс.Чтобы сделать это, я бы изложил код следующим образом:

  1. Возьмите свой контент и разделите его вот так: $parts = preg_split('/[{}]/', $page_string);

  2. Напишите рекурсивную функцию над частями со следующими критериями:

    • Остановка, когда длина аргумента равна < 3
    • В противном случае верните новый массив, состоящий из
    • $arg[0] .load_data($arg[1]) .$аргумент[2]
    • плюс все, что осталось в $argv[3 ...]
  3. Запустите свою функцию через $parts.

Вы можете сделать это без регулярных выражений (не дай бог), что-то вроде:

//return true if $str ends with $sub
function endsWith($str,$sub) {
    return ( substr( $str, strlen( $str ) - strlen( $sub ) ) === $sub );
}

$theStringWithVars = "blah.php cool.php awesome.php";
$sub = '.php';
$splitStr = split(" ", $theStringWithVars);
for($i=0;$i<count($splitStr);$i++) {
    if(endsWith(trim($splitStr[$i]),$sub)) {
        //file_get_contents($splitStr[$i]) etc...
    }    
}

Навскидку, ты хочешь этого:

// load the "template" file
$input = file_get_contents($template_file_name);

// define a callback. Each time the regex matches something, it will call this function.
// whatever this function returns will be inserted as the replacement
function replaceCallback($matches){
  // match zero will be the entire match - eg {FOO}. 
  // match 1 will be just the bits inside the curly braces because of the grouping parens in the regex - eg FOO
  // convert it to lowercase and append ".html", so you're loading foo.html

  // then return the contents of that file.
  // BEWARE. GIANT MASSIVE SECURITY HOLES ABOUND. DO NOT DO THIS
  return file_get_contents( strtolower($matches[1]) . ".html" );
};
// run the actual replace method giving it our pattern, the callback, and the input file contents
$output = preg_replace_callback("\{([-A-Z]+)\}", replaceCallback, $input);

// todo: print the output

Теперь я объясню регулярное выражение

 \{([-A-Z]+)\}
  • В \{ и \} просто скажите, чтобы оно соответствовало фигурным скобкам.Вам нужны косые черты, так как { и } являются специальными символами, поэтому они нуждаются в экранировании.
  • В ( и ) создайте группировку.По сути, это позволяет вам извлекать определенные части совпадения.Я использую это в функции выше, чтобы просто сопоставлять объекты внутри фигурных скобок, не сопоставляя сами фигурные скобки.Если бы я этого не сделал, то мне нужно было бы раздеть { и } выбыл из игры, что было бы досадно
  • В [-A-Z] говорит "сопоставьте любой символ верхнего регистра, или -
  • В + после того , как [-A-Z] означает, что нам нужно иметь по крайней мере 1 символ, но мы можем иметь до любого числа.

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

Используйте ассоциативный массив и str_replace для выполнения ваших замен.str_replace поддерживает массивы для одновременного выполнения нескольких подстановок.Замена одной строки, без циклов.

Например:

$substitutions = array('{VAR}'=>file_get_contents('VAR.php'),
'{TEST}'=>file_get_contents('TEST.php'),
...
);

$outputContents = str_replace( array_keys($substitutions), $substitutions, $outputContents);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top