2012-08-12 47 views
2

我想通過垂直條爆炸一個字符串。這是很容易的部分。但是,我不希望拆分影響由圓括號包圍的子字符串。這意味着我需要一個字符串,如:爆炸字符串,除了被圓括號包圍的地方?

Hello (sir|maam).|Hi there! 

爆炸到:

Array 
(
    [0] => Hello (sir|maam). 
    [1] => Hi there! 
) 

通過使用正常爆炸的功能,我不相信有一種方法來告訴它忽略吧被括號包圍。不過,我有一些想法。

我知道可以通過正常爆炸字符串,然後遍歷數組並將包含(的字符串之間的所有內容合併到包含)的最後一個字符串來完成此操作。不過,我有一種感覺,應該有一種更優雅的方式來實現這一點。

我對不對?考慮到這些限制,是否有更少的代碼密集型方法將字符串拆分爲數組?

+5

http://php.net/manual/en/function.preg-match.php – PeeHaa 2012-08-12 00:52:59

+0

爲什麼只是將分隔符更改爲獨特的字符?像#或者甚至是字符組合#@ – Oras 2012-08-12 01:26:15

+1

@Petra這是簡單的部分,正則表達式是很難的部分;) – tigrang 2012-08-12 01:41:16

回答

3

如果你能保證括號將是平衡的,從來沒有嵌套(即,如果永遠不會有一個'Oops(!''(nested stuff (like this)|oops)'),並且永遠不會有一個||你關心匹配括號外爲空字符串,那麼這應該幫助:

preg_match_all('/(?:[^(|]|\([^)]*\))+/', $your_string, $matches); 
$parts = $matches[0]; 

它會匹配[要麼(字符,這不是一個|(),或()封閉東西,這不是一個)(其中包括|)],儘可能多次(但至少一次)。簡短版本:它會在匹配的括號部分之間創建|,而不是分隔符。

另一種可能性,那就是略少神祕:

$parts = preg_split('/\|(?![^(]*\))/', $your_string); 

採用的是前向斷言取消其參賽資格是,再接一個)如果有不之間的任何(|。對於parens仍然有些不妥協,但它會匹配兩個|之間的空字符串。

+0

絕對是一個正則表達式的有趣用法。謝謝! :)我想我會最終使用這個。 – Nathanael 2012-08-12 03:05:10

0

直到有人寫一個基於正則表達式的解決方案,我懷疑是可能的一次通過,這應該工作。這是對代碼的直接轉換。

<?php 
function my_explode($str) 
{ 
    $ret = array(); $in_parenths = 0; $pos = 0; 
    for($i=0;$i<strlen($str);$i++) 
    { 
     $c = $str[$i]; 

     if($c == '|' && !$in_parenths) { 
      $ret[] = substr($str, $pos, $i-$pos); 
      $pos = $i+1; 
     } 
     elseif($c == '(') $in_parenths++; 
     elseif($c == ')') $in_parenths--; 
    } 
    if($pos > 0) $ret[] = substr($str, $pos); 

    return $ret; 
} 

$str = "My|Hello (sir|maam).|Hi there!"; 
var_dump(my_explode($str));