Анализатор текста выдает ложное отрицание на игле, когда стог сена содержит дополнительную разметку

#php #regex #parsing

#php #регулярное выражение #синтаксический анализ

Вопрос:

Приведенный ниже код принимает ключевое слово и строку текста (очищенную от html-тегов) и определяет, появляется ли ключевое слово в последнем предложении очищенного содержимого.

Есть один сбой, который я не могу понять. Когда в конце содержимого содержится хотя бы пустое пространство или тег абзаца с неразрывным пробелом, т.Е.

 This is the last sentence.<p>amp;nbsp;</p>
  

Я получаю ложноотрицательное значение (нет совпадения), несмотря на то, что (1) Ключевое слово определенно присутствует в последнем предложении и (2) функция strip_tags () должна обеспечить отсутствие проблемы с появлением тега в конце.

Кто-нибудь понимает, почему это может происходить?

 function plugin_get_kw_last_sentence($post) {
    $theContent = strip_tags(strtolower($post->post_content));
    $theKeyword = 'test';
    $thePiecesByKeyword = plugin_get_chunk_keyword($theKeyword,$theContent);
    if (count($thePiecesByKeyword)>0) {
        $theCount = $thePiecesByKeyword[count($thePiecesByKeyword)-1];
        $theCount = trim($theCount,'.');
        if (substr_count($theCount,'.')>0) {
            return FALSE;
        } else {
            return TRUE;
        }
    }
    return FALSE;
}

function plugin_get_chunk_keyword($theKeyword, $theContent) {
    if (!plugin_get_kw_in_content($theKeyword,$theContent)) {
        return array();
    }

    $myPieceReturn = preg_split('/b' . $theKeyword . 'b/i', $theContent);
    return $myPieceReturn;
}
  

Комментарии:

1. Вам нужно дважды перерезать границы этих слов, \ b

2. @Tony, спасибо. Можете ли вы помочь мне понять, почему?

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

4. Спасибо, Тони, я ценю ваше объяснение и ваше элегантное решение вопроса.

Ответ №1:

У вас там происходит много такого, что, я думаю, может быть описано только в регулярном выражении, если я правильно понимаю вашу логику. Нельзя ли свести всю логику к этому:

 function plugin_get_kw_last_sentence($post) {
    $pattern = '/' . $theKeyword . '[^.!?]*[.!?][^.!?]*$/';
    $subject = strip_tags(strtolower($post->post_content));
    return preg_match($pattern, $subject);
}
  

Регулярное выражение совпадает, когда оно находит ваше ключевое слово и знак препинания в конце последнего предложения, между которыми нет других знаков препинания в конце предложения.

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

Комментарии:

1. @Tony, звучит логично. Сейчас запускаю его через несколько тестов. Я полагаю, я мог бы разработать обходной путь для наиболее распространенных исключений, которые вы упоминаете. На самом деле, это была бы неплохая идея. Спасибо за помощь.

2. @Tony, я пытаюсь протестировать, но получаю: Предупреждение: preg_match() [function.preg-match]: Неизвестный модификатор ‘*’ (в строке preg_match()). ?

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

4. Это исправило сообщение об ошибке. Спасибо. Проблема в том, что ваша функция, как и моя, все еще возвращает ЛОЖНЫЕ отрицания. Мое ключевое слово — «ключевое слово test» в последнем предложении, которое звучит так: «Ключевое слово test находится здесь. <p>amp;nbsp;</p>»

5. …Однако, когда я меняю предложение на: «Ключевое слово test находится здесь». Я получаю return TRUE, как и ожидал.