如何获取正则表达式不匹配的数据?

时间:2012-03-03 21:22:30

标签: php regex parsing preg-match-all

我正在解析推文,作为向数据库添加提醒的快捷方式。推文看起来像这样:

$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 = '@username Tweet content [Project Name] #notes !high_priority';

有谁知道怎么做?

4 个答案:

答案 0 :(得分:2)

将正则表达式匹配的文本替换为空字符串。剩下的就是正则表达式所没有的匹配。

答案 1 :(得分:0)

使用preg_split代替preg_match_all,然后您可以获得其中的所有组件,作为Brent的答案的替代方法,它会返回单个字符串。请注意,许多匹配可能为空。

答案 2 :(得分:0)

我没有测试过这段代码,但我认为这种非正则表达式的想法可能对您有所帮助。基本上你用空格分割字符串然后解析每个部分。这种方法意味着零件的顺序无关紧要。

它有点棘手,因为内容和项目可以跨越多个部分,但我认为我的代码应该处理它。它还假设您每条推文只有一个#标签,用户,项目和优先级。例如,如果有多个主题标签,只需将它们放在数组中而不是字符串中。最后,它没有任何错误处理来检测/防止发生奇怪的事情。

这是我未经测试的代码:

$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);

答案 3 :(得分:0)

我认为你的RegEx中有一个错误,你在[a-zA-Z_]之前使用\ w,看起来你想要匹配空格,而\ w匹配单词字符。你可以这样做(对于这个小部分):

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

由于您似乎已经遍历匹配以获取不同的部分,因此您可以为要匹配的纯文本创建子模式,并将其与模式的其余部分连接。这样你只需要一个额外的匹配。这将适用于内容的不同顺序,只要您在循环匹配时区分匹配的部分。