2

我有一个带有自定义标记的字符串,用于保存带有和弦、制表符、音符等的歌曲。它包含

各种括号中的东西:\[.+?\],, 箭头:\[[.+?\]],,等等 ......\(.+?\)
<-{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

4

1 回答 1

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

如果要向正则表达式添加更多模式,请确保在开头放置更长的模式,以免它们被错误地匹配为错误的类型。

于 2013-05-03T13:07:40.970 回答