2011-05-12 80 views
4

我明白了,因爲正則表達式本質上是無狀態的,要實現複雜的匹配而不訴諸補充應用邏輯是相當困難的,但是我很想知道下面是否可能。正則表達式匹配空白,但跳過部分

匹配所有的空白,很容易:\s+

但跳過某些分隔符之間的空白,在我的情況 <pre></pre> nostrip

是否有任何技巧可以實現這個目標?我正在考慮沿着兩個單獨的比賽,一個爲所有空白,一個爲 <pre>nostrip部分,並以某種方式否定後者從前者。

"This is some text NOSTRIP this is more text NOSTRIP some more text." 
// becomes 
"ThisissometextNOSTRIP this is more text NOSTRIPsomemoretext." 

給出 標籤 NOSTRIP部分是無關緊要的,我不會試圖解析 的嵌套樹 HTML或任何,只是整理一個文本文件,但節省了 <pre> blocks nostrip部分中的空格,原因很明顯。

更好?


這是最終我跟去了。我相信它可以在幾個地方進行優化,但現在它可以很好地工作。

public function stripWhitespace($html, Array $skipTags = array('pre')){ 
    foreach($skipTags as &$tag){ 
     $tag = "<{$tag}.*?/{$tag}>"; 
    } 
    $skipped = array(); 
    $buffer = preg_replace_callback('#(?<tag>' . implode('|', $skipTags) . ')#si', 
     function($match) use(&$skipped){ 
      $skipped[] = $match['tag']; 
      return "\x1D" . (count($skipped) - 1) . "\x1D"; 
     }, $html 
    ); 
    $buffer = preg_replace('#\s+#si', ' ', $buffer); 
    $buffer = preg_replace('#(?:(?<=>)\s|\s(?=<))#si', '', $buffer); 
    for($i = count($skipped) - 1; $i >= 0; $i--){ 
     $buffer = str_replace("\x1D{$i}\x1D", $skipped[$i], $buffer); 
    } 
    return $buffer; 
} 
+2

你在html上使用正則表達式嗎?爲什麼? – 2011-05-12 20:51:51

+0

實際上,你需要的更加複雜:正則表達式還需要確保在

和空格之間沒有
,反之亦然。 – abesto 2011-05-12 20:54:30

+1

http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags – mellamokb 2011-05-12 21:02:22

回答

2

我你使用的是腳本語言,我會使用多步驟的方法。

  • 拔出NOSTRIP部分,並保存到一個數組中,並用標記替換(###或東西)
  • 更換所有的空間
  • 重新注入所有保存NOSTRIP網頁摘要
+0

謝謝**馬特**;這就是我朝向的方向,我只是好奇如何在沒有多個步驟的情況下實現這一目標。另外,是** PHP **。我希望能夠按照某種方式「打斷」正則表達式解析,當它碰到一個'nostrip'標記時,然後在打到另一個時打開它。 – Dan 2011-05-12 21:46:25

+0

另外,將作爲臨時分隔符使用的安全字符/字符是什麼? (*閱讀;你/你認識的其他人/標準慣例使用了什麼?*)我在想也許是一個晦澀的控制角色,比如'BEL' – Dan 2011-05-12 21:54:18

+0

我總是發現自己在一次性情況下使用正則表達式,因此更容易理解該文件的唯一字符串。像「~~~」通常起作用。但是,正如你所建議的那樣,沒有一個萬無一失的字符串。你只能用更復雜的字符串來降低風險。試一下:##〜!!〜!##((__# – Matt 2011-05-12 22:52:23

1

我曾經創造了一組功能,以減少HTML輸出空白:

function minify($html) { 
     if(empty($html)) { 
       return $html; 
     } 
     $html = preg_replace('/^(.*)((<pre.*<\/pre>)(.*?))?$/Ues', "parse('$1').'$3'.minify('$4')", $html); 
     return $html; 
} 

function parse($html) { 
     var_dump('1'.$html); 
     // Replace multiple spaces with a single space 
     $html = preg_replace('/(\s+)/m', ' ', $html); 
     // Remove spaces that are followed by either > or < 
     $html = preg_replace('/ ([<>])/', '$1', $html); 
     $html = str_replace('> ', '>', $html); 
     return $html; 
} 

$html = minify($html); 

你可能有稍微修改以適應您的需求。

+0

謝謝** Arjan **;我會給它不久之後,他嘗試了一些東西。 – Dan 2011-05-12 21:52:56