2017-09-06 74 views
0

我想知道是否有一种优雅的方式来执行preg_replace,但仍保留被preg_replace取代的内容。preg_replace - 保留变量中已被替换的内容

举例想象一个包含随机站点HTML的字符串。我想从该字符串中删除<head>作进一步处理,并仍将<head>元素的内容保留在额外变量中(例如,用于解析元标记)。

我能想到的两种可能做到这一点(不使用全局变量):

if (preg_match('%<head>(.*?)</head>%ism', $html, $matches)) { 
    $html = preg_replace('%<head>(.*?)</head>%ism', '', $html); 
    $head = $matches[1]; 
} 

这其中有执行正则表达式这两次是不理想的。

$head = ''; 
$html = preg_replace_callback(
     "%<head>(.*?)</head>%ism", 
     function ($match) use (&$head) { 
      $head .= $match[1]; 
      return ''; 
     }, 
     $html 
); 

我想知道是否有一个更优雅/高效的方式来做到这一点。

+0

@WiktorStribiżew那么他如何在这种情况下捕获比赛? – Steve

+0

我会去参加第一场比赛。我不认为还有更好的办法,但是你可以使用'str_replace'来获得比赛来保存第二个正则表达式 – apokryfos

+0

我没有注意到你正在存储比赛。第二个是最高效的。 –

回答

2

您正在尝试做的事:检索头部内容,并删除头部内容。试图将两个(相似,但是)不同的东西合并成一个只会导致挫败感。

就我个人而言,我会选择两个建议的选项中的第一个,但将正则表达式放入一个变量中并重复使用,而不是输入正则表达式两次。使之后更容易。

但是再次,你有没有考虑过使用解析器?

$dom = new DOMDocument(); 
$dom->loadHTML($html_source_here); 
$headelement = $dom->getElementsByTagName('head')[0]; 
$headhtml = $dom->saveHTML($headelement); 
$headelement->parentNode->removeChild($headelement); 
$result = $dom->saveHTML(); 

现在你有两个$headelement(其中将包括<head>...</head>包装,完整的,可能是它的任何属性),并与<head>删除HTML。