Замена текста (исключая между тегами)

Тема в разделе "Регулярные выражения", создана пользователем 4erepaha13, 7 дек 2010.

Статус темы:
Закрыта.
Модераторы: xpert13
  1. 4erepaha13

    4erepaha13

    Регистр.:
    20 июн 2009
    Сообщения:
    155
    Симпатии:
    17
    В большом массиве текста необходимо произвести массовые замены.
    Для этой цели похоже что подойдет пример с пхп.нет:
    PHP:
    $patterns = array();
    $patterns[0] = '/quick/';
    $patterns[1] = '/brown/';
    $patterns[2] = '/fox/';
    $replacements = array();
    $replacements[2] = 'bear';
    $replacements[1] = 'black';
    $replacements[0] = 'slow';
    echo 
    preg_replace($patterns$replacements$string);
    Но есть заковыка - нужно оставлять неизменным текст внутри некоторых тегов
    <a.*?a> (не править анкоры и титле)
    <img.*?> (не править альты)
    <h.*?\/h.> (не править заголовки)
    и для этого надо "Перейти по ссылке".
    Подскажите- как это все вместе увязать, потому что теорию на практику корректного синтаксиса пока подобрать не удалось.
     
  2. B0nuse

    B0nuse Постоялец

    Регистр.:
    6 июн 2009
    Сообщения:
    106
    Симпатии:
    21
    Думаю можно использовать отрицаниие в регулярке
    (?!слово)
     
  3. Yoorok

    Yoorok Создатель

    Регистр.:
    7 май 2008
    Сообщения:
    21
    Симпатии:
    0
    Добрый день. Подскажите пожалуйста.
    Есть регулярка eregi_replace('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&,()//=]+)', 'Перейти по ссылке', $text)

    Как мне ее модифицировать так, чтобы под шаблон попадали только ссылки, которые либо начинаются с новой строки, либо содержат перед собой пробел

    Добавлено через 51 секунду
    я как понимаю мне (?!слово) тоже подходит... а как описать (?!пробел или новая строка)
     
  4. pitkina

    pitkina

    Регистр.:
    1 апр 2007
    Сообщения:
    253
    Симпатии:
    176
    подмаски и отрицания в паттерне усложнят задачу, обычно для этого достаточно просто разделить html на элементы и через foreach произвести замену с условиями

    PHP:
    // $html

    $find_replace = array( 'find1'=>'repl1''find2'=>'repl2' ); // массив поиск/замена

    $parts preg_split('/(<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))>)/'$html, -1PREG_SPLIT_NO_EMPTY PREG_SPLIT_DELIM_CAPTURE);

    foreach (
    $parts as $part) {
       if(!
    preg_match('/^<(a|img|h)/i',$part)) $part strtr($part,$find_replace); // условие пропуска
       
    $res_html .= $part;
    }

    // $res_html;
    2.
    например так:
    PHP:
    $text preg_replace('#(?:^|\s)((f|ht)tp://)\S+#im','\\1',$text);
     
  5. 4erepaha13

    4erepaha13

    Регистр.:
    20 июн 2009
    Сообщения:
    155
    Симпатии:
    17
    Эта регулярка сломала мозг и помоему там есть чтото сверх того, что мне нужно :)

    Решил написать свою,
    PHP:
    $parts preg_split('/(<img[^>]*?>|<a\s.*?>.*?a>|<h\d.*?h\d>)/i'$html, -1PREG_SPLIT_NO_EMPTY PREG_SPLIT_DELIM_CAPTURE);
    навскидку работает.
     
  6. Liver

    Liver

    Регистр.:
    24 сен 2008
    Сообщения:
    316
    Симпатии:
    91
    Я делал подобную задачу так - заменял все тэги на вставки типа ###TAG1### и собирал эти тэги в массив. Получал сплошной текст. Изменял его регуляркой без всяких там опережений и потом заменял тэги обратно. Для скорости можно использовать модификатор e.
     
  7. 4erepaha13

    4erepaha13

    Регистр.:
    20 июн 2009
    Сообщения:
    155
    Симпатии:
    17
    Метод Pitkina оказался таки самым простым и эффективным, а в результате обкатки регулярка пришла к такому конечному виду
    PHP:
    <.*?>|<a\s.*?>.*?a>|<h\d.*?h\d>
    Т.е. не править в любых одиночных тегах, не править в ссылках и в заголовках.
    Самое интересное, что именно к такому виду тоже пришел автор плагина Перейти по ссылке
     
Статус темы:
Закрыта.