За последние 24 часа нас посетили 17819 программистов и 1678 роботов. Сейчас ищут 805 программистов ...

Найти 3-е вхождение символа в строке и заменить

Тема в разделе "Сделайте за меня", создана пользователем romagromov, 17 дек 2015.

  1. romagromov

    romagromov Активный пользователь

    С нами с:
    17 дек 2015
    Сообщения:
    73
    Симпатии:
    0
    Я готов учится и могу заплатить.

    Но с наскока в такой функции я не могу разобраться.
    Допустим мне в одной переменной надо сделать 2 замены на 2 разных содержимых.
    Здесь
    Код (PHP):
    1. echo preg_replace_callback('/<\/p>/',function($m) use ($change) {static $i=0;return(3==++$i)?$change:$m[0];},$line);
    делается одна замена

    Нужно найти другой символ и заменить другим содержимым.
    Я сделал это в 2 прохода. И в принципе, с этим можно жить. Оно же работает. Но хочу понять, как это сделать компактнее.
    Начал искать использование OR в preg_replace_callback - не нашел.
    Отсюда возникает вопрос - это вообще возможно?
     
  2. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    возможно. просто ты не программист и не можешь создать алгоритма. а нет алгоритма - нет понимания того какие инструменты надо использовать. что значит "OR в preg_replace_callback"?
     
  3. romagromov

    romagromov Активный пользователь

    С нами с:
    17 дек 2015
    Сообщения:
    73
    Симпатии:
    0
    Грубо говоря, если есть A, то заменяем на А1 ИЛИ если есть B, то заменяем на B1

    Или использовать 2 массива - один с искомыми данными, второй с заменами.

    Но в таком случае, непонятно, как первую замену делать на 3-м вхождении, в вторую на 8-м.

    Я сделал коряво:

    Код (PHP):
    1. $text1="text1";
    2. $text2="text2";
    3. $firstreplace = preg_replace_callback('/<p>/',function($m) use ($text1) {static $i=0;return(3==++$i)?$text1:$m[0];},$adstext);
    4. $secondreplace = preg_replace_callback('/<p>/',function($m) use ($text2) {static $i=0;return(8==++$i)?$text2:$m[0];},$firstreplace);
    5. echo $secondreplace;
    Хочу сделать нормально.
     
  4. romagromov

    romagromov Активный пользователь

    С нами с:
    17 дек 2015
    Сообщения:
    73
    Симпатии:
    0
    Подскажите хотя бы - идея с 2-мя массивами правильная?
     
  5. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    в смысле с двумя массивами?
     
  6. romagromov

    romagromov Активный пользователь

    С нами с:
    17 дек 2015
    Сообщения:
    73
    Симпатии:
    0
    Как я уже писал, надо в переменной найти 2 разных текста и заменить 2-мя разными заменами.
    Причем первую замену после 3-го вхождения, а вторую после 8-го.
    То есть, если в тексте 3 раза встречается "А", то третье вхождение заменяем на "A1"
    Дальше, если в тексте 8 раз встречается "B", то восьмое вхождение заменяем на "B1"

    Мы уже имеем код, делающий 1-ю замену

    Код (PHP):
    1. $text1="text1";
    2. $firstreplace = preg_replace_callback('/<p>/',function($m) use ($text1) {static $i=0;return(3==++$i)?$text1:$m[0];},$adstext); 
    Дальше, как я уже говорил, я вторую замену я сделал тупо 2-мя проходами

    Код (PHP):
    1. $text1="text1";
    2. $text2="text2";
    3. $firstreplace = preg_replace_callback('/<p>/',function($m) use ($text1) {static $i=0;return(3==++$i)?$text1:$m[0];},$adstext);
    4. $secondreplace = preg_replace_callback('/<p>/',function($m) use ($text2) {static $i=0;return(8==++$i)?$text2:$m[0];},$firstreplace);
    5. echo $secondreplace;
    6.  
    Теперь, про 2 массива.

    Может будет правильно использовать 2 массива и делать замены одним проходом.

    Код (PHP):
    1. $massive1 = array("A", "B");
    2. $massive2 = array("A1", "B1"); 
     
  7. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    я бы одним массивом делал. ключи - что искать, значение - массив на что заменять и как регулярно.
     
  8. romagromov

    romagromov Активный пользователь

    С нами с:
    17 дек 2015
    Сообщения:
    73
    Симпатии:
    0
    Не понимаю, как должен выглядеть такой массив.

    Добавлено спустя 16 секунд:
    Не понимаю, как должен выглядеть такой массив.
    Пример?
     
  9. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    сочувствую
    Код (PHP):
    1. array('search' => array('replace', 2));
     
  10. romagromov

    romagromov Активный пользователь

    С нами с:
    17 дек 2015
    Сообщения:
    73
    Симпатии:
    0
    А второе искомое слово и вторая замена, по восьмому вхождению?

    И как эту конструкцию вставить в preg_replace_callback ?
    Конкретно сюда

    Код (PHP):
    1. $firstreplace = preg_replace_callback('/<p>/',function($m) use ($text1) {static $i=0;return(3==++$i)?$text1:$m[0];},$adstext); 
     
  11. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    Код (PHP):
    1.   'search' => array('replace', 2),
    2.   'search2' => array('replace2', 8),
    3. );
    ну тема нынче в разделе где по желанию делают. у меня желания нет :D
    там всё очень просто. ключи упаковал как шаблон регулярки а в колбэке - сравнил с ключом, извлек метаниформацию, сравнил номер прохода, произвел замену.

    Добавлено спустя 37 минут 41 секунду:
    ой ладно, сейчас начнется нытье на тему того что если не хочешь помогать то вообще не пиши в тему противный и всё такое...

    Код (PHP):
    1. <?php
    2. // строка-жертва
    3. $str = <<<STR
    4. 1 aaa bbb ccc 2 aaa bbb ccc 3 aaa bbb ccc 4 aaa bbb ccc 5 aaa bbb ccc
    5. 6 aaa bbb ccc 7 aaa bbb ccc 8 aaa bbb ccc 9 aaa bbb ccc 10 aaa bbb ccc
    6. 11 aaa bbb ccc 12 aaa bbb ccc 13 aaa bbb ccc 14 aaa bbb ccc 15 aaa bbb ccc
    7. 16 aaa bbb ccc 17 aaa bbb ccc 18 aaa bbb ccc 19 aaa bbb ccc 0 aaa bbb ccc
    8. STR;
    9.  
    10. // тот самый смешной массив искать-заменять
    11. $data = [
    12.   // что искать раз
    13.   'aaa'=> [
    14.     // на что заменять раз
    15.     'AaA',
    16.     // заменять только второе вхождение
    17.     2,
    18.   ],
    19.  
    20.   // что искать два
    21.   'bbb'=> [
    22.     // на что заменять два
    23.     'AbC',
    24.     // замеять только третье вхождение
    25.     3,
    26.   ],
    27.  
    28.   // что искать три
    29.   'ccc'=> [
    30.     // на что заменять три
    31.     'Defg',
    32.     // заменять КАЖДОЕ пятое вхождение
    33.     -5,
    34.   ],
    35.  
    36. ];
    37.  
    38. // создаем регулярное выражение (не скажу зачем отдельно вынес ибо это личное)
    39. $regex = '/' . implode('|', array_keys($data)) . '/';
    40.  
    41. // применяем замены к строке
    42. $str = preg_replace_callback($regex, function($m) use ($data)
    43. {
    44.   // массив для счетчиков совпадений по искомым конструкциям
    45.   static $counters = [];
    46.   // массив регулярности замен
    47.   static $regular = [];
    48.   
    49.   // если переданное в эм-ноль слово встретилось в массиве "искать-заменять"...
    50.   if (isset($data[$m[0]]))
    51.   {
    52.     // ... решим что у нас с регулярностью ...
    53.     if (!isset($regular[$m[0]]))
    54.     {
    55.       // если отричательное число - заменяем каждое ЭНное совпадение
    56.       // иначе (6ля ну "если положительное число") - только конкретное совпадение
    57.       $regular[$m[0]] = ($data[$m[0]][1] < 0);
    58.     }
    59.  
    60.     // ... и проверим есть ли у нас счетчик для такого слова
    61.     if (!isset($counters[$m[0]]))
    62.     {
    63.       // его нет - объявим
    64.       $counters[$m[0]] = 0;
    65.     }
    66.  
    67.     // ничего необычного - если N-ность совпадает с:
    68.     // * заявленной положительным числом или
    69.     // * регулярностью заявленной отрицательным числом
    70.     // то ...
    71.     $counters[$m[0]]++;
    72.     if (
    73.       ($regular[$m[0]] && 0 == ($counters[$m[0]] % $data[$m[0]][1]))
    74.         ||
    75.       ($counters[$m[0]] == $data[$m[0]][1])
    76.       )
    77.     {
    78.       // ... производим замену
    79.       return $data[$m[0]][0];
    80.     }
    81.   }
    82.  
    83.   // иначе положим на место что брали
    84.   return $m[0];
    85. }, $str);
    86.  
    87. // насладимся результатом
    88. var_dump($str);
    89.  
    90. // скажем спасибо человеку за пару минут потраченного времени
    91. echo 'Spasibo, Ganzal!!!', "\n";
    92.  
    93. // eof
    94.  
    Код (PHP):
    1. string(293) "1 aaa bbb ccc 2 AaA bbb ccc 3 aaa AbC ccc 4 aaa bbb ccc 5 aaa bbb Defg
    2. 6 aaa bbb ccc 7 aaa bbb ccc 8 aaa bbb ccc 9 aaa bbb ccc 10 aaa bbb Defg
    3. 11 aaa bbb ccc 12 aaa bbb ccc 13 aaa bbb ccc 14 aaa bbb ccc 15 aaa bbb Defg
    4. 16 aaa bbb ccc 17 aaa bbb ccc 18 aaa bbb ccc 19 aaa bbb ccc 0 aaa bbb Defg"
    5. Spasibo, Ganzal!!!
    6.  
    воркс лайк э шарм.
     
  12. rodent90

    rodent90 Новичок

    С нами с:
    26 мар 2015
    Сообщения:
    533
    Симпатии:
    37
    Все равно у них не верное условие..., оно не будет работать правильно, там на неравенство нужно условие, а не на равенство.
    Код (PHP):
    1. function text($str, $search = '', $replace = '', $pos = 0) {
    2.     if (!$str || !$search || !$replace || !$pos) {
    3.         return;
    4.     }
    5.     $search = preg_quote($search);
    6.     return preg_replace_callback("/{$search}/iu", function($matches) use($pos, $replace) {
    7.         static $i = 0;
    8.         if ($pos !== ++$i) {
    9.             return $matches[0];
    10.         }
    11.         return $replace;
    12.     }, $str);
    13. } 
    Теперь отрабатывает верно.
    Код (PHP):
    1. echo text('Текст, тЕкст, ТЕКст', 'Текст', '2 текст', 2); //Текст, 2 текст, ТЕКст 
    Если в позицию писать 1 или 2 или 3, он правильно будет заменять текст.
     
  13. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    не, чувак, похоже у них всё правильно. ты где-то запутался.
     
  14. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    preg_replace_callback, function, use... извращенцы :)

    Код (PHP):
    1. $s = 'бе бе 123 123 123 123 abc abc abc abc';
    2. var_dump(preg_replace(['/(.*2.*2.*)(2)/U', '/(.*b.*b.*b.*)(b)/U'], ['${1}0', '${1}B'], $s));
    3.  
     
  15. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    Chushkin, убил нахрен :D
     
  16. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    В смысле?
     
  17. rodent90

    rodent90 Новичок

    С нами с:
    26 мар 2015
    Сообщения:
    533
    Симпатии:
    37
  18. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Какой вирус породил эпидемию возгласов? :)
    Вопрос тот же: в смысле?
     
  19. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    Chushkin, один из первых моих начальников (там просто начальников много было) очень любил повторять две фразы: "крутая техника в руках идиотов - кусок пластмассы" (но сейчас не об этом) и "профессионализм не в знании инструмента, а в умении его применять". ты очень элегантно применил одну единственную функцию. просто браво!
     
  20. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Аа, в этом смысле. Ну, да, бывает.
     
  21. rodent90

    rodent90 Новичок

    С нами с:
    26 мар 2015
    Сообщения:
    533
    Симпатии:
    37
    Увидев твой вариант, мне показался он немного пугающим, тем, что нужно составлять регулярки всегда и квотить их, однако это будет правильнее, но сложнее и времени нужно больше, чтобы, что - то действительное стоящее вышло.
    Но вышло довольно элегантно. Просветил)
     
  22. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Ну да. Регулярки вообще довольно мощная вещь, если "въехать".
     
  23. denis01

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

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
    Выходит что нужно генерировать регулярное выражение под каждый случай?
     
  24. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Нет. Это частное решение для ТС.
     
  25. rodent90

    rodent90 Новичок

    С нами с:
    26 мар 2015
    Сообщения:
    533
    Симпатии:
    37
    Все же, удобнее будет 1, 2, 3, более естественно выглядит, а остальное ты уже дал. :)
    Хоть и как вариант вообще еще лучше заюзать и в правду регулярками ;)