preg_match_all: Почему «это» соответствует, но «это» не будет? - PullRequest
3 голосов
/ 17 июля 2010

Итак, я в основном пытаюсь сопоставить что-либо внутри (и включая) теги объекта, с этим:

<?php preg_match_all('/<object(.*)<\/object>/', $blah, $blahBlah); ?>

Находит соответствие для этого:

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="250" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=9048799&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="250" src="http://vimeo.com/moogaloop.swf?clip_id=9048799&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object>

Но это не будет соответствовать:

<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5630744&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5630744&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object>

Есть идеи, почему? Спасибо за понимание.


ETA: Поскольку мой подход, возможно, был ошибочным с самого начала, вот некоторые сведения о том, что я пытаюсь сделать.

Это для сайта Wordpress. Я использую плагин, который преобразует ярлык в полный код для вставки видео. Плагин был недавно (к счастью) обновлен, чтобы сделать код более действительным.

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

Вот вся функция (некоторые из них будут иметь смысл, только если вы работали с Wordpress):

<?php
function catch_that_video() {
  global $post, $posts;
  $the_video = '';
  ob_start();
  ob_end_clean();
  $output = preg_match_all('/<object(.*)<\/object>/', $post->post_content, $vid_matches);
  $the_video = $vid_matches [1] [0];
  if(empty($the_video)){ $the_video = 0; }
  return $the_video;
}
?>

1 Ответ

1 голос
/ 17 июля 2010

Единственное, что приходит на ум - это одиночные и множественные строки.

/<object(.*)<\/object>/m

Это должно совпадать в нескольких строках.

На этой странице руководства рассматриваются модификаторы:

http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

Обновление:

После дальнейшего изучения, m не является правильным модификатором (из руководства):

м (PCRE_MULTILINE) По умолчанию PCRE рассматривает строку темы как состоящую из одна «строка» символов (даже если на самом деле он содержит несколько строки). «Начало линии» метасимвол (^) соответствует только на начало строки, а "конец строка "только метасимвол ($) соответствует в конце строки или перед завершающий перевод строки (если не модификатор D установлено). Это так же, как Perl. Когда этот модификатор установлен, «запуск» конструкций линии "и" конец строки " соответствовать сразу после или непосредственно перед любой новой строкой в предметная строка соответственно тоже как в самом начале и в конце. Это эквивалентно модификатору Perl's / m. Если в нём нет символов \ n строка темы, или нет вхождений ^ или $ в шаблоне, устанавливая это Модификатор не действует.

(Подчеркну свое.)

Правильный модификатор будет s, что позволит метасимволу точки . соответствовать символам новой строки.

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

<code>$input = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="250" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=9048799&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="250" src="http://vimeo.com/moogaloop.swf?clip_id=9048799&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object>';

$input2 = '<object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5630744&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5630744&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object>';

$matches = array();
preg_match_all('/<object(.*)<\/object>/', $input, $matches); 
echo '<br />$input<pre>';
var_dump($matches);
echo '
'; $ match2 = array (); preg_match_all ('/ /', $ input2, $ match2); echo '
$ input2
';
var_dump($matches2);
echo '
';

Двигаемся дальше:

Что вы пытаетесь достичь с помощью этих двух строк?

ob_start();
ob_end_clean();

Это открывает новый выходной буфер и немедленно убивает его. (См. Немного о стековых выходных буферах в документации .)

Есть ли причина установить это значение равным 0, а не сказать null?

if(empty($the_video)){ $the_video = 0; }

Лично я бы установил его на null, когда объявлял его, и полагался бы на то, что это не сработает, если нет совпадений. Вот как бы я написал эту функцию, предполагая, что $post является глобальным WordPress. (Лично я бы просто передал это в функцию, поскольку у меня есть презрение к большинству глобалов.)

function catch_that_video() 
{
  global $post;

  $the_video = null;
  $vid_matches = array();

  if(preg_match('/<object.*<\/object>/', $post->post_content, $vid_matches))
  {
    $the_video = $vid_matches[0];
  }

  return $the_video;
}

Я изменил его, чтобы использовать preg_match вместо preg_match_all, так как вы используете только первое совпадение. Это, конечно, можно изменить, чтобы использовать preg_match_all, если это необходимо. Тем не менее, соответствующее регулярное выражение будет боль создавать. (Добавление модификатора s к приведенному выше регулярному выражению для работы с несколькими строками приведет к захвату всего: от первого открывающего тега <object> до последнего закрывающего тега </object>. Я даже не хочу думать о попытке прийти с регулярным выражением, чтобы покрыть несколько строк и захватить отдельные <object>...</object> блоки.)

Однако это не отвечает первоначальному вопросу о том, почему 2-й объектный блок не сопоставляется. Я бы сосредоточил свое расследование на попытке обнаружить разницу между двумя строками. Если бы проблема заключалась в разнице между окончаниями строк, я бы использовал что-то вроде VIM в Linux, так как это показывало бы `^ M 'вместо \ r в окончаниях строк. Как насчет html-кодирования строки? Может ли это быть возможной проблемой?

...