2012-03-03 37 views
1

我正在解析推文,作爲向數據庫添加提醒的快捷方式。推文看起來像這樣:如何獲得正則表達式不匹配的數據?

$tweet = '#notes @username !high_priority [Project Name] Tweet content'; 

我使用以下正則表達式來獲得#,@,!和[項目]

$match = preg_match_all('/(#\\w*[a-zA-Z_]+\\w*)|(!\\w*[a-zA-Z_]+\\w*)|(@\\w*[a-zA-Z_]+\\w*)|(\\[[^\\]]*\\])/i', 
    $tweet, 
    $matches); 

我想知道怎麼也得剩下的「分享Tweet內容」,這樣簡化版,匹配正則表達式一切都應該被保存到一個變量。

而且,如果將鳴叫的東西更像是匹配順序事:

$tweet = '@username Tweet content [Project Name] #notes !high_priority'; 

有誰知道該怎麼做?

+1

你覺得'\ w'做什麼?它與'[a-zA-Z]'幾乎相同' – Vyktor 2012-03-03 21:30:32

+0

只需循環遍歷所有匹配,然後在每個不以#,@,!開始的匹配中組成一個字符串。 &[ – Yaniro 2012-03-03 21:44:47

回答

2

將正則表達式匹配的文本替換爲空字符串。剩下的是正則表達式沒有匹配的東西。

+0

我正在使用: '$ content = preg_replace('/(#\\ w * [a-zA-Z _] + \\ w *)|(!\\ w * [a-zA-Z_ ] +(w *)|(@ \ w * [a-zA-Z _] + \\ w *)|(\\ [[^ \\]] * \\])/ i','', $ subject);' 然後只是修剪剩餘的空白。 – 2012-03-04 11:28:11

0

使用preg_split而不是preg_match_all,那麼您將獲得所有組件之間的所有組件,作爲Brent的答案的替代方法,它返回單個字符串。請注意,許多比賽可能是空的。

+0

我還使用'preg_match'來鍵入遍歷匹配的答案,保存偏移量以檢索數據而不復制任何字符串,但這對於此用例來說太重了。我猜想羅馬有很多種方式。 – 2012-03-03 22:30:45

0

我還沒有測試過這段代碼,但我認爲這個非正則表達式的想法可能對你更好。基本上你用空格分割字符串,然後解析每一塊。這種方法意味着零件的訂單無關緊要。

由於內容和項目可以跨越多個部分,但我認爲我的代碼應該可以處理該問題,所以它有點棘手。它還假定您每個推文只有一個hashtag,用戶,項目和優先級。例如,如果會有多個hashtags,只需將它們放入一個數組而不是一個字符串。最後,它沒有任何錯誤處理來檢測/防止奇怪的事情發生。

這裏是我的未經測試的代碼:

$data = array(
    'hash' => '', 
    'user' => '', 
    'priority' => '', 
    'project' => '', 
    'content' => '' 
); 

$parsingProjectName = false; 
foreach(explode(' ', $tweet) as $piece) 
{ 
    switch(substr($piece, 0, 1)) 
    { 
     case '#': 
      $data['hash'] = substr($piece, 1); 
      break; 
     case '@': 
      $data['user'] = substr($piece, 1); 
      break; 
     case '!': 
      $data['priority'] = substr($piece, 1); 
      break; 
     case '[': 
      // Check if the project name is longer than 1 word 
      if(strpos($piece, -1) == ']') 
      { 
       $data['project'] = substr($piece, 1, -1); 
      } 
      else 
      { 
       // There will be more to parse in the next piece(s) 
       $parsingProjectName = true; 
       $data['project'] = substr($piece, 1) . ' '; 
      } 
      break; 
     default: 
      if($parsingProjectName) 
      { 
       // Are we at the end yet? 
       if(strpos($piece, -1) == ']') 
       { 
        // Yes we are 
        $data['project'] .= substr($piece, 1, -1); 
        $parsingProjectName = false; 
       } 
       else 
       { 
        // Nope, there is more 
        $data['project'] .= substr($piece, 1) . ' '; 
       } 
      } 
      else 
      { 
       // We aren't in the middle of parsing the project name, and this piece doesn't start with one of the special chars, so assume it is content 
       $data['content'] .= $piece . ' '; 
      } 
    } 
} 

// There will be an extra space on the end; remove it 
$data['content'] = substr($data['content'], 0, -1); 
+0

順便說一句,您可能需要仔細檢查我對substr的使用情況。我用它來檢查第一個字符,最後一個字符,並抓住除了第一個或最後一個字符以外的所有內容。我希望它是有道理的和有效的:P – 2012-03-03 22:53:25

0

我認爲你有一個錯誤在你的正則表達式,你使用\ W前[A-ZA-Z_],它看起來像你想匹配的空白,而\ w匹配字字符。你可以這樣做的(對於這個小區域):

...\\s*[\\w_]+\\s*... 

正如你似乎已經循環了比賽,以獲得不同的部分,你可以創建你想要的純文本的子模式匹配和或連接它與你的模式的其餘部分。這樣你只需要一次追加比賽。只要您在循環匹配時區分匹配的部分,這將適用於內容的不同順序。