Вопрос по php, html-parsing, regex, html – Регулярное выражение игнорировать совпадения между <script> tags

0

Я извиняюсь, потому что у меня очень мало знаний о Regex, и я даже не понимаю точно, что делает это регулярное выражение (я не писал его -источник) кроме того, что он ищет определенный термин, чтобы его можно было выделить.

Вот регулярное выражение:

/(\b$term|$term\b)(?!([^<]+)?>)/iu

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

Кто-нибудь может изменить это таким образом? Я сообщу об этом автору плагина, который написал этот reg-ex, для включения в будущие выпуски.

Edit: Вот функция, из которой она исходит:

function relevanssi_highlight_terms($excerpt, $query) {
    $type = get_option("relevanssi_highlight");
    if ("none" == $type) {
        return $excerpt;
    }

    switch ($type) {
        case "mark":                        // thanks to Jeff Byrnes
            $start_emp = "<mark>";
            $end_emp = "</mark>";
            break;
        case "strong":
            $start_emp = "<strong>";
            $end_emp = "</strong>";
            break;
        case "em":
            $start_emp = "<em>";
            $end_emp = "</em>";
            break;
        case "col":
            $col = get_option("relevanssi_txt_col");
            if (!$col) $col = "#ff0000";
            $start_emp = "<span style='color: $col'>";
            $end_emp = "</span>";
            break;
        case "bgcol":
            $col = get_option("relevanssi_bg_col");
            if (!$col) $col = "#ff0000";
            $start_emp = "<span style='background-color: $col'>";
            $end_emp = "</span>";
            break;
        case "css":
            $css = get_option("relevanssi_css");
            if (!$css) $css = "color: #ff0000";
            $start_emp = "<span style='$css'>";
            $end_emp = "</span>";
            break;
        case "class":
            $css = get_option("relevanssi_class");
            if (!$css) $css = "relevanssi-query-term";
            $start_emp = "<span class='$css'>";
            $end_emp = "</span>";
            break;
        default:
            return $excerpt;
    }

    $start_emp_token = "*[/";
    $end_emp_token = "\]*";

    if ( function_exists('mb_internal_encoding') )
        mb_internal_encoding("UTF-8");

    $terms = array_keys(relevanssi_tokenize($query, $remove_stopwords = true));

    $phrases = relevanssi_extract_phrases(stripslashes($query));

    $non_phrase_terms = array();
    foreach ($phrases as $phrase) {
        $phrase_terms = array_keys(relevanssi_tokenize($phrase, false));
        foreach ($terms as $term) {
            if (!in_array($term, $phrase_terms)) {
                $non_phrase_terms[] = $term;
            }
        }
        $terms = $non_phrase_terms;
        $terms[] = $phrase;
    }

    usort($terms, 'relevanssi_strlen_sort');

    get_option('relevanssi_word_boundaries', 'on') == 'on' ? $word_boundaries = true : $word_boundaries = false;
    foreach ($terms as $term) {
        $pr_term = preg_quote($term, '/');
        if ($word_boundaries) {
            $excerpt = preg_replace("/(\b$pr_term|$pr_term\b)(?!([^<]+)?>)/iu", $start_emp_token . '\\1' . $end_emp_token, $excerpt);
        }
        else {
            $excerpt = preg_replace("/($pr_term)(?!([^<]+)?>)/iu", $start_emp_token . '\\1' . $end_emp_token, $excerpt);
        }
        // thanks to http://pureform.wordpress.com/2008/01/04/matching-a-word-characters-outside-of-html-tags/
    }

    $excerpt = relevanssi_remove_nested_highlights($excerpt, $start_emp_token, $end_emp_token);

    $excerpt = str_replace($start_emp_token, $start_emp, $excerpt);
    $excerpt = str_replace($end_emp_token, $end_emp, $excerpt);
    $excerpt = str_replace($end_emp . $start_emp, "", $excerpt);
    if (function_exists('mb_ereg_replace')) {
        $pattern = $end_emp . '\s*' . $start_emp;
        $excerpt = mb_ereg_replace($pattern, " ", $excerpt);
    }

    return $excerpt;
}
люди будут злиться на вас за использование reg ex для HTML, это бесполезно Scott Selby
Не смешивайте регулярные выражения с HTML! hsz
@hsz Это не мой плагин. Он уже использует это регулярное выражение, я пытаюсь исправить некоторые ложные совпадения, которые он создает. George Reith
@ScottSelby см. Выше George Reith
1) Это звучит как плохо написанный плагин. Избегайте этого, если это возможно. 2) Вы действительно хотите пойти по пути пользовательского редактирования плагина, чтобы вы застряли с этой версией и никогда не могли ее обновить? Огромные подводные камни лежат вниз по дороге. 3) Если выmust пользуйтесь им, я не думаю, что вы предоставили достаточно информации для ответа на этот вопрос. Ключ - это часть плагина, которая игнорирует HTML, чего нет в приведенной выше строке кода. dan1111

Ваш Ответ

4   ответа
0

воскрешая этот древний вопрос, потому что у него было простое решение, которое не было упомянуто. Эта ситуация прямо из моего любимого вопроса на данный момент,Совпадение (или замена) шаблона, за исключением ситуаций s1, s2, s3 и т. Д.

Вы хотите изменить следующее регулярное выражение, чтобы исключить что-либо между<script> а также</script>:

(\bSOMETERM|SOMETERM\b)(?!([^<]+)?>)

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

Со всеми заявлениями об ограничении соответствия HTML в регулярных выражениях, чтобы исключить что-либо между<script> а также</script>, вы можете просто добавить это в начало вашего регулярного выражения:

<script>.*?</script>(*SKIP)(*F)|

поэтому регулярное выражение становится:

<script>.*?</script>(*SKIP)(*F)|(\bSOMETERM|SOMETERM\b)(?!([^<]+)?>)

How does this work?

Левая сторонаOR (Т.е.|) совпадения завершены<script...</script> теги, то сознательно не удается. Правая сторона соответствует тому, что вы соответствовали ранее, и мы знаем, что это правильные вещи, потому что, если бы это было между тегами сценария, это бы не сработало.

Reference

Как сопоставить (или заменить) шаблон кроме случаев s1, s2, s3 ...

2

Parse the HTML with a proper HTML parser Ignore the strings that are within the <script> tags.

Вы не хотите пытаться анализировать HTML с помощью регулярных выражений. Вот объяснение того, почему:http://htmlparsing.com/regexes.html

Это сделает вас грустным в долгосрочной перспективе. Пожалуйста, посмотрите на остальныеhttp://htmlparsing.com/ для некоторых указателей, которые могли бы начать вас.

Это невозможно в контексте моего вопроса. Это часть уже встроенного плагина для WordPress CMS. Я не переписываю плагин, я пытаюсь изменить небольшую часть его поведения. Регулярное выражение просто ищет определенное слово на странице, чтобы выделить его, оно уже игнорирует html, но не игнорирует содержимое<script> теги. George Reith
1

смотреть за утверждениями должны быть зафиксированы в длине, вы не можете использовать их для поиска предыдущего<script> тегsomewhere до обыскаterm.

Итак, после того, как вы замените все вхождения желаемогоtermвам нужен второй проход, чтобы вернуть обратно эти вхожденияmodified term которые кажутся внутри<script> тег.

# provide some sample data
$excerpt = 'My name is bob!

And bob is cool.

<script type="text/javascript">
var bobby = "It works fine even if you already have tagged the term <em>bob</em> inside the script tag.";
alert(bobby);

var bob = 5;
</script>

Yeah, the word "bob" works fine.';

$start_emp_token = '<em>';
$end_emp_token = '</em>';
$pr_term = 'bob';

# replace everything (not in a tag)
$excerpt = preg_replace("/(\b$pr_term|$pr_term\b)(?!([^<]+)?>)/iu", $start_emp_token . '$1' . $end_emp_token, $excerpt);

# undo some of the replacements
$excerpt = preg_replace_callback('#(<script(?:[^>]*)>)(.*?)(</script>)#is',
                       create_function(
                         '$matches',
                         'global $start_emp_token, $end_emp_token, $pr_term;
                          return $matches[1].str_replace("$start_emp_token$pr_term$end_emp_token", "$pr_term", $matches[2]).$matches[3];'
                       ),
                       $excerpt);

var_dump($excerpt);

Код выше производит следующий вывод:

string(271) "My name is <em>bob</em>!

And <em>bob</em> is cool.

<script type="text/javascript">
var bobby = "It works fine even if you already have tagged the term <em>bob</em> inside the script tag.";
alert(bobby);

var bob = 5;
</script>

Yeah, the word "<em>bob</em>" works fine."
Спасибо, но, похоже, ничего не делает. George Reith
Ваше регулярное выражение успешно соответствуетscript теги, но это не удаление токенов. George Reith
Код работает в этом сценарии, но, похоже, не может найти$start_emp_token а также$end_emp_token когда используется в строке с большим количеством вариаций, таких как мой исходный код HTML. Увидетьrcnhca.org.uk/sites/first_steps/test.php где я использую ваш пример кода, но просто заменил строку моим исходным кодом HTML. См. Строку 115, где не удается извлечь токены. George Reith
Проигнорируйте мой последний комментарий какem теги, где уже в строке. Похоже, работает в вашем сценарии, но не при добавлении в плагин. Я думаю, что это связано с видео, внедряемымSWFobject и какой-то вопрос времени. Я думаю, что мой единственный вариант - отключить функцию выделения. Позор. George Reith
Для меня это работает просто отлично. Я только что отредактировал свой ответ, включив некоторые примеры данных. Можете ли вы попробовать и посмотреть, работает ли он для вас тоже?
0

что было бы приемлемо удалить теги сценария перед выполнением поиска.

$data = preg_replace('/<\s*script.*?\/script\s*>/iu', '', $data);

Этот код может помочь с этим.

Похожие вопросы