Как получить данные, которые не соответствуют регулярному выражению? - PullRequest
1 голос
/ 04 марта 2012

Я анализирую твит как быстрый способ добавления напоминаний в базу данных. Твит будет выглядеть примерно так:

$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 ]

2 голосов
/ 04 марта 2012

Замените текст, которому соответствует ваше регулярное выражение, на пустую строку. Осталось то, что не соответствовало регулярному выражению.

0 голосов
/ 04 марта 2012

Я думаю, что у вас есть ошибка в вашем RegEx, когда вы используете \ w перед [a-zA-Z_], которая выглядит так, как будто вы хотите найти пробел, тогда как \ w соответствует слову-символам.Вы могли бы сделать это таким образом (для этой маленькой части):

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

Поскольку вы, кажется, уже просматриваете совпадения, чтобы получить разные части, вы можете создать подшаблон для простого текста, который выхотите сопоставить и / или соединить его с остальной частью вашего шаблона.Таким образом, у вас будет только один дополнительный матч.Это будет работать и для другого порядка содержимого, если вы будете различать совпадающие части во время циклического поиска совпадений.

0 голосов
/ 04 марта 2012

Я не тестировал этот код, но я думаю, что эта идея без регулярных выражений может работать лучше для вас.По сути, вы разбиваете строку на пробелы, а затем анализируете каждый фрагмент.Этот подход означает, что не имеет значения, в каком порядке детали.

Это немного сложно, потому что контент и проект могут состоять из нескольких частей, но я думаю, что мой код должен с этим справитьсяТакже предполагается, что у вас есть только один хэштег, пользователь, проект и приоритет на твит.Например, если будет несколько хэштегов, просто поместите их в массив вместо строки.Наконец, он не обрабатывает ошибки, чтобы обнаружить / предотвратить странные вещи.

Вот мой непроверенный код:

$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 голосов
/ 04 марта 2012

Используйте preg_split вместо preg_match_all, тогда вы получите все промежуточные компоненты в качестве альтернативы ответу Брента, который возвращает одну строку.Обратите внимание, что многие совпадения могут быть пустыми.

...