preg_replace только вне тегов? (... мы не говорим полный "html-разбор", просто немного уценки) - PullRequest
3 голосов
/ 05 января 2011

Какой самый простой способ применить выделение некоторого текста, исключая текст внутри случайных тегов "<...>"?

РАЗЪЯСНЕНИЕ : я хочу, чтобы существующие теги были сохранены!

$t = 
preg_replace(
  "/(markdown)/",
  "<strong>$1</strong>",
"This is essentially plain text apart from a few html tags generated with some
simplified markdown rules: <a href=markdown.html>[see here]</a>");

Который должен отображаться как:

"Это по сути простой текст, за исключением нескольких HTML-тегов, сгенерированных с помощью некоторых упрощенных уценок правил: см. Здесь"

... НО НЕ ПРОПУСКАЙТЕ текст внутри тега привязки (т. Е. <a href=markdown.html>).

Я слышал аргументы не разбора html с регулярными выражениями, но здесьмы говорим по существу о простом тексте, за исключением минимального разбора некоторого кода уценки.

Ответы [ 5 ]

3 голосов
/ 05 января 2011

На самом деле это работает нормально:

<?php
$item="markdown";
$t="This is essentially plain text apart from a few html tags generated 
with some simplified markdown rules: <a href=markdown.html>[see here]</a>";

//_____1. apply emphasis_____
$t = preg_replace("|($item)|","<strong>$1</strong>",$t);

// "This is essentially plain text apart from a few html tags generated 
// with some simplified <strong>markdown</strong> rules: <a href=
// <strong>markdown</strong>.html>[see here]</a>"

//_____2. remove emphasis if WITHIN opening and closing tag____
$t = preg_replace("|(<[^>]+?)(<strong>($item)</strong>)([^<]+?>)|","$1$3$4",$t);

// this preserves the text before ($1), after ($4) 
// and inside <strong>..</strong> ($2), but without the tags ($3)

// "This is essentially plain text apart from a few html tags generated
// with some simplified <strong>markdown</strong> rules: <a href=markdown.html>
// [see here]</a>"

?>

Строка типа $item="odd|string" может вызвать некоторые проблемы, но я все равно не буду использовать такую ​​строку ... (вероятно, нужны htmlentities(...) или тому подобное ...)

1 голос
/ 05 января 2011

Вы можете разбить строку на тег ‍ / ‍ без тега детали, используя preg_split:

$parts = preg_split('/(<(?:[^"\'>]|"[^"<]*"|\'[^\'<]*\')*>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);

ТогдаВы можете перебирать части, пропуская каждую четную часть (т. е. тег части) и применять к нему замену:

for ($i=0, $n=count($parts); $i<$n; $i+=2) {
    $parts[$i] = preg_replace("/(markdown)/", "<strong>$1</strong>", $parts[$i]);
}

В конце все соедините вместе с implode:

$str = implode('', $parts);

Но учтите, что это действительно не лучшее решение.Вам лучше использовать правильный HTML-парсер, такой как PHP-библиотека DOM.См., Например, следующие вопросы:

0 голосов
/ 05 января 2011

Вы можете разбить вашу строку на массив в каждом '<' или '>', используя preg_split(), затем выполнить цикл по этому массиву и заменить только в записях, не начинающихся с '>'.После этого вы объединяете ваш массив в строку, используя implode().

0 голосов
/ 05 января 2011

на самом деле это не очень эффективно, но у меня это сработало

$your_string = '...';

$search = 'markdown';
$left = '<strong>';
$right = '</strong>';

$left_Q = preg_quote($left, '#');
$right_Q = preg_quote($right, '#');
$search_Q = preg_quote($search, '#');
while(preg_match('#(>|^)[^<]*(?<!'.$left_Q.')'.$search_Q.'(?!'.$right_Q.')[^>]*(<|$)#isU', $your_string))
  $your_string = preg_replace('#(^[^<]*|>[^<]*)(?<!'.$left_Q.')('.$search_Q.')(?!'.$right_Q.')([^>]*<|[^>]*$)#isU', '${1}'.$left.'${2}'.$right.'${3}', $your_string);

echo $your_string;
0 голосов
/ 05 января 2011

Это регулярное выражение должно удалять все открывающие и закрывающие теги HTML: /(<[.*?]>)+/

Вы можете использовать его с preg_replace, например:

$test = "Hello <strong>World!</strong>";
$regex = "/(<.*?>)+/";


$result = preg_replace($regex,"",$test);
...