Замена тегов на Включения в PHP с RegExps - PullRequest
0 голосов
/ 07 апреля 2009

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

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

Чем это полезно? Это полезно для перехвата WordPress.

Ответы [ 5 ]

1 голос
/ 07 апреля 2009

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

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

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

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

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

1 голос
/ 07 апреля 2009

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

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

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

  3. После того, как у вас будут 3 части, вам нужно будет запустить свое включение и соединить их вместе.

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

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

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

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

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

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

0 голосов
/ 07 апреля 2009

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

Используйте ассоциативный массив и 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);
0 голосов
/ 07 апреля 2009

С макушки головы, ты хочешь это:

// 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 символ, но мы можем иметь любое число.
0 голосов
/ 07 апреля 2009

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

//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...
    }    
}
...