2017-09-06 72 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。