preg_match_all:为什么“这个”匹配但“那个”不匹配?

时间:2010-07-17 02:06:24

标签: php regex preg-match-all

所以,我基本上试图匹配任何内部(包括)对象标签,以及:

<?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 个答案:

答案 0 :(得分:1)

唯一想到的是单线对多线。

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

这应该匹配多行。

本手册介绍了修饰符:

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

更新

经过进一步调查,m不是正确的修饰符(来自手册):

  

m(PCRE_MULTILINE)       默认情况下,PCRE将主题字符串视为由a组成   单个“行”的字符(即使   它实际上包含几个   新行)。 “行的起点”   元字符(^)仅匹配   字符串的开头,而“结尾   line“metacharacter($)仅匹配   在字符串的末尾,或在a之前   终止换行符(除非D修饰符   已设定)。这与Perl相同。   设置此修改器后,“开始   行“和”行尾“构造   马上跟着或匹配   紧接在任何新行之前   主题字符串,也分别   就像在开始和结束时一样。这是   相当于Perl的/ m修饰符。如果   a中没有“\ n”字符   主题字符串,或者没有出现^   或者在一个模式中,设置这个   修饰符没有效果。

(强调我自己。)

正确的修饰符为s,这将允许点元字符.匹配换行符。

继续更新问题,正则表达式本身匹配这两个输入,如果这些输入是简单的字符串。我不知道是什么导致了实际问题。

$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 '</pre>';

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

继续:

你想用这两行来完成什么?

ob_start();
ob_end_clean();

这将打开一个新的输出缓冲区并立即将其杀死。 (请参阅documentation中有关堆叠输出缓冲区的内容。)

是否有理由将此设置为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>块。)

但是,这并没有回答原始问题,即为什么第二个对象块没有匹配。我会集中精力研究这两个字符串之间的区别。如果问题是行结尾之间的区别,我会在Linux上使用类似VIM的东西,因为它会在行结尾显示“^ M”代替\ r \ n。字符串的html编码怎么样?可能是一个可能的问题吗?