2010-07-09 87 views
1

我需要一個函數或一些正則表達式來分割字符串中的空格,但將HTML標記視爲單詞。拆分單詞但不包含HTML如果它包含HTML

$str = 'one two <a href="">three</a> four'; 
$x = explode(" ", $str); 
print_r($x); 

/* Returns: 
    Array 
(
    [0] => one 
    [1] => two 
    [2] => <a 
    [3] => href="">three</a> 
    [4] => four 
) 

Looking for way to return: 

Array 
(
    [0] => one 
    [1] => two 
    [2] => <a href="">three</a> 
    [3] => four 
) 

*/ 

任何想法?謝謝

+0

我正在寫一個函數,這個..應該就會完成.. – Fosco 2010-07-09 13:26:33

回答

2

這是簡單一些,然後上面,還沒有完全測試,但給它一個鏡頭。

$str = 'one two <a href="">three</a> four'; 

if(preg_match_all('%(<[^<]+.*?>|[^\s]+)%', $str, $matches)) { 
    array_shift($matches); 
    print_r($matches); 
} 

這裏是另一個我5分鐘左右的作品好一點的測試版本:

$str = 'one two <a href="omfg hi I have spaces"> three</a> four <script type="javascript"> var a = "hello"; </script><random tag>la la la la<nested>hello?</nested></random tag>'; 

if(preg_match_all('%(<[^<]+.*?>|[^\s]+)%', preg_replace('%([\s]\<|\>[\s])%', '$1', $str), $matches)) { 
    array_shift($matches); 
    echo '<pre>'; 
    print_r($matches); 
    echo '</pre>'; 
} 
+0

可以工作,但如果字符串中有
則失敗 – fire 2010-07-09 16:10:34

0

在使用爆炸之前和之後,可以對字符串進行正則表達式替換。

所以它會進入爆炸一樣

<a_href="">test</a> 

超越任何簡單的情況下,雖然你在談論解析HTML這不是做正則表達式的好事。

這裏有很多關於解析HTML的問題。也許你可以適應他們。

2
preg_split('/(<([A-Z][A-Z0-9]*)\b[^>]*>(.*?)</\1>)|| /, $text) 

這有時會奏效。它分成一個標籤集,或者一個空間。

但是,你想要的不是那麼簡單。您應該涵蓋所有嵌套標籤的情況,內容有空格的標籤([a href] Foo Bar Baz [/ a])等等。 爲此,你最好實現一個合適的XML(html)解析器。

但是在我看來你對這個數組有目的。它是數數「單詞」嗎?如果是這樣,解決方案將是一個更簡單的函數調用,從文本中剝離所有HTML(strip_tags()),然後應用您的wordsplitter並對它們進行計數。

0

我編寫並測試了這個自定義函數。試試看,讓我知道你的想法。

function fireSplit($str) { 
    if (strpos($str,"<") === FALSE) return explode(" ",$str); 
    $str = trim($str); 
    $out = array(); 
    $curIdx = 0; 
    $endIdx = strlen($str) -1; 

    while ($curIdx <= $endIdx) { 
     if (substr($str,$curIdx,1) == " ") { 
       $curIdx += 1; 
       continue; 
     } 
     $nextspace = strpos($str," ",$curIdx); 
     $nexttag = strpos($str,"<",$curIdx); 
     $nexttag2 = strpos($str,"/",$nexttag); 
     $nexttag3 = strpos($str,">",$nexttag2); 

     if ($nextspace === FALSE) { 
       $out[] = substr($str,$curIdx); 
       $curIdx = $endIdx + 1; 
       continue; 
     } 

     if ($nexttag !== FALSE && $nexttag < $nextspace && $nexttag2 !== FALSE && $nexttag3 !== FALSE) { 
       $out[] = substr($str,$curIdx,($nexttag3 - $curIdx + 1)); 
       $curIdx = $nexttag3 + 1; 
     } else { 
       $out[] = substr($str,$curIdx,($nextspace - $curIdx)); 
       $curIdx = $nextspace; 
     } 
    } 
return $out; 
} 

我叫:

fireSplit("one two <a href=\"haha\">three</a> four"); 
fireSplit("a <b>strong</b> c d e f"); 

,它返回:

array(4) { 
    [0]=> 
    string(3) "one" 
    [1]=> 
    string(3) "two" 
    [2]=> 
    string(24) "<a href="haha">three</a>" 
    [3]=> 
    string(4) "four" 
} 

array(6) { 
    [0]=> 
    string(1) "a" 
    [1]=> 
    string(13) "<b>strong</b>" 
    [2]=> 
    string(1) "c" 
    [3]=> 
    string(1) "d" 
    [4]=> 
    string(1) "e" 
    [5]=> 
    string(1) "f" 
} 
+0

附加測試可能發現一個或兩個我沒有考慮的情景......我只想到了一個,標籤結束後的下一個字符不是空格。 – Fosco 2010-07-09 13:48:28

+0

我更新了函數以解釋我上次評論中的錯過情景。 – Fosco 2010-07-09 13:59:31

+0

@Fosco邪惡的功能取$ str ='a c d e f';我得到致命錯誤:允許的內存大小爲104857600字節,因此它必須在某處泄漏內存?! – fire 2010-07-09 15:54:15