За последние 24 часа нас посетили 16962 программиста и 1652 робота. Сейчас ищут 989 программистов ...

Вопрос по preg_replace_callback

Тема в разделе "PHP для новичков", создана пользователем VLK, 19 июл 2014.

  1. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Вопросы следующие, как я заметил preg_replace_callback находит вхождение по искомому регулярному выражению и отправляет массив данных в функцию, а потом заменяет найденное на то, что возвращает функция, например:

    Код (PHP):
    1. function fns($data) {
    2.         foreach ($data as $k => $v) {
    3.         echo "<div>{$k} => {$v}</div>";
    4.     }
    5.     return strtoupper($data[0]);
    6. }
    7.  
    8. $preg = '/(world)/i';
    9. $str = 'hello world! this world is great';
    10.  
    11. echo preg_replace_callback($preg, 'fns', $str);
    12. // 0 => world
    13. // 1 => world
    14. // hello WORLD! this WORLD is great   
    Мне надо что бы еще отправляло позицию найденного вхождения, желательно начало и конец, это возможно? (дополнительный поиск в самой функции не пойдет)
    Так же вопрос такой, допустим мне надо в определенном диапазоне найти слово и заменить его всего один раз (для этого в принципе и нужны позиции) возможно ли как нибудь после первой замены обрубить выполнение preg_replace_callback? (параметры limit и count тут вроде как не катят т.к. они считают сколько раз была вызвана функция, а не сколько раз в ней что то конкретное сделалось)

    Самое главное, приведенный пример это только пример, на самом деле поиск и замена осуществляется в html тегах, по этому замена без использования регулярных выражений не катит.

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

    к примеру:
    Код (PHP):
    1. $str = 'hello world! this world is great. world is big!';
    мне надо заменить слова world начиная с 20 позиции, т.е. в этом предложении первое слово world будет пропущено, второе будет заменено, а до третьего preg_replace_callback уже не должно дойти, и результат должен быть такой:
    Код (PHP):
    1. // hello world! this WORLD is great. world is big!    
     
  2. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    вообще-то limit как раз и ограничивает количество замен,
    позицию не сохраняет
     
  3. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Замена происходит в любом случае, на то, что возвращает функция, а функция у меня должна работает следующим образом:

    и мне нужно что бы preg_replace_callback вырубалась после того как произойдет:
    к примеру:
    Код (PHP):
    1. $str = 'hello world! this world is great. world is big!';
    мне надо заменить слова world начиная с 20 позиции, т.е. в этом предложении первое слово world будет пропущено, второе будет заменено, а до третьего preg_replace_callback уже не должно дойти, и результат должен быть такой:
    Код (PHP):
    1. // hello world! this WORLD is great. world is big!  
     
  4. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    Код (PHP):
    1. echo preg_replace_callback($preg, 'fns', $str, 1); 
    находит все, заменяет только limit раз.

    какая конечная цель?
     
  5. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Надо найти слово которое находится на позиции от 20 и дальше и заменить его один раз, точно такие же слова которые находят до 20-й позиции не должны быть изменены, слова после произведенный замены не должны быть изменены.

    Задача:
    Входные данные:
    Код (Text):
    1. 'hello world! this world is great. world is big!'
    На выходе я должен получить:
    Код (Text):
    1. 'hello world! this WORLD is great. world is big!'
     
  6. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    внезапно.
    Код (PHP):
    1. <?php
    2.  
    3. $html = "hello world! this world is great. world is big!";
    4. $needle = "world";
    5. $replace = 'МИР';
    6. $lastPos = 0;
    7. $positions = array();
    8. $replacePos = 2;
    9.  
    10. while (($lastPos = strpos($html, $needle, $lastPos)) !== FALSE) {
    11.     $positions[] = $lastPos;
    12.     $lastPos = $lastPos + strlen($needle);
    13. }
    14.  
    15. $realPos = $replacePos - 1;
    16. if (isset($positions[$realPos])) {
    17.     $html = substr_replace($html, $replace, $positions[$realPos], strlen($needle));
    18. }
    19. echo $html;
    Но надо на реальной задаче прогнать, производительность протестить
     
  7. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Может я не совсем въехал в задачу, но может быть так?
    Код (PHP):
    1. function replaceFromPos($str, $reg, $repl, $pos = 0, $cnt = -1){
    2.     return substr($str, 0, $pos).preg_replace($reg, $repl, substr($str, $pos, strlen($str)), $cnt);
    3. }
    4. $text = 'hello world! this world is great. world is big!';
    5. $pattern = '/(world)/i';
    6. $replacement = 'WORLD';
    7. echo replaceFromPos($text, $pattern, $replacement, 10, 1);
    8. // результат:
    9. // hello world! this WORLD is great. world is big!   
    P.S. закинул в песочницу для тестирования
     
  8. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    Deonis, у тебя substr_replace() с количеством замен получился :)
    А в моём случае находит позицию каждого вхождения и для n-ого вхождения заменяет
    Фиг его знает что в реальности требуется
     
  9. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Ладно, давайте так, можно как нибудь сделать так, что бы preg_replace_callback передавала в функцию еще и позицию найденного вхождения?
    Если да, то как.
    Если нет, то мне не повезло.
     
  10. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    не повезло тебе
     
  11. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Ну и на том спасибо :)
    Вообще я нашел выход из своей проблемы, я изменил сам подход и все ок.
     
  12. Хыиуду

    Хыиуду Активный пользователь

    С нами с:
    3 июн 2014
    Сообщения:
    618
    Симпатии:
    5
    Ну, в общем-то, напрашивалось:
    Код (PHP):
    1. $str = substr($str,0,20).preg_replace('......', '......', $substr($str, 20), 1); 
     
  13. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Можно.
    use(&$var)
     
  14. loveaboveall

    loveaboveall Новичок

    С нами с:
    8 янв 2015
    Сообщения:
    2
    Симпатии:
    0
    Обоснуйте! Что это такое написали?
     
  15. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    передача по ссылке! в лямбда-функцию!! читайте апи используемых функций!!!!!1!1!1111 я угадал что тут разговор на повышенных тонах? :D
     
  16. loveaboveall

    loveaboveall Новичок

    С нами с:
    8 янв 2015
    Сообщения:
    2
    Симпатии:
    0
    нет, не угадали. Не понимаю сути, если сама функция не возвращает позицию, то каким образом что0то может помочь?