2013-05-03 30 views
2

我有一個自定義標記的字符串保存歌曲的和絃,tabulatures,注意事項等,包含各種括號如何用PHP解析異構標記?

事情:\[.+?\]\[[.+?\]]\(.+?\)
箭頭:<-{3,}>\-{3,}><\-{3,}
等...

示例文本可能是

Text Text [something] 
---> 
Text (something 021213) 

現在我想的標記解析成令牌,相應的類的對象,這將如下所示(括號內爲相匹配份)

ParsedBlock_Text ("Text Text ") 
ParsedBlock_Chord ("something") 
ParsedBlock_Text (" ") 
ParsedBlock_NewColumn 
ParsedBlock_Text (" text ") 
ParsedBlock_ChordDiagram ("something 021213") 

我知道如何與它們匹配的數組,但無論是我必須在每個不同的圖案匹配,並保存偏移量以正確排序數組,或者我一次匹配它們,並且我不知道哪一個匹配。

感謝,MK

+2

不要通過正則表達式方法啓動這種複雜的解析任務。那很快就會變成一場可怕的惡夢。尋找一個「編譯器 - 編譯器」或「解析器生成器」,而是使用一種形式語法語法將標記編譯爲內部結構的工具。通過這種方式,您可以使用隨時可用的引擎,而不必再次執行所有經典錯誤,並強制自己爲標記定義真正的語法。 「石灰」可能是一個起點:http://sourceforge.net/projects/lime-php/ – arkascha 2013-05-03 12:15:23

+0

謝謝,我會看看它,似乎更合乎邏輯的方法。 – SmallhillCZ 2013-05-07 09:29:48

回答

1

假設你沒有嘗試拼圖這些結構,這將令牌化文本:

function ParseText($text) { 
    $re = '/\[\[(?P<DoubleBracket>.*?)]]|\[(?P<Bracket>.*?)]|\((?P<Paren>.*?)\)|(?<Arrow><---+>?|---+>)/s'; 
    $keys = array('DoubleBracket', 'Bracket', 'Paren', 'Arrow'); 
    $result = array(); 
    $lastStart = 0; 
    if (preg_match_all($re, $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { 
     foreach ($matches as $match) { 
      $start = $match[0][1]; 
      $prefix = substr($text, $lastStart, $start - $lastStart); 
      $lastStart = $start + strlen($match[0][0]); 
      if ($prefix != '' && !ctype_space($prefix)) { 
       $result []= array('Text', trim($prefix)); 
      } 
      foreach ($keys as $key) { 
       if (isset($match[$key]) && $match[$key][1] >= 0) { 
        $result []= array($key, $match[$key][0]); 
        break; 
       } 
      } 
     } 
    } 
    $prefix = substr($text, $lastStart); 
    if ($prefix != '' && !ctype_space($prefix)) { 
     $result []= array('Text', trim($prefix)); 
    } 
    return $result; 
} 

例子:

$mytext = <<<'EOT' 
Text Text [something] 
---> 
Text (something 021213) 
More Text 
EOT; 

$parsed = ParseText($mytext); 
foreach ($parsed as $item) { 
    print_r($item); 
} 

輸出:

Array 
(
    [0] => Text 
    [1] => Text Text 
) 
Array 
(
    [0] => Bracket 
    [1] => something 
) 
Array 
(
    [0] => Arrow 
    [1] => ---> 
) 
Array 
(
    [0] => Text 
    [1] => Text 
) 
Array 
(
    [0] => Paren 
    [1] => something 021213 
) 
Array 
(
    [0] => Text 
    [1] => More Text 
) 

http://ideone.com/kJQrBw

如果你想更多的模式添加到正則表達式,請確保你把較長的模式在一開始,所以他們不誤匹配的錯誤類型。