За последние 24 часа нас посетили 17055 программистов и 1835 роботов. Сейчас ищут 1645 программистов ...

Возможно ли такое организовать при помощи рег. выражений

Тема в разделе "Регулярные выражения", создана пользователем VLK, 15 июн 2014.

  1. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    С вот этим текстом:
    Код (Text):
    1. $str = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела';
    не верно работает код из этого поста - viewtopic.php?f=13&t=48868#p392547
    пишет:
    т.е. сжирает часть текста, который он не должен сжирать.

    из этого поста - viewtopic.php?f=13&t=48868#p392496
    верхний тоже сжирает часть текста, а вот второй работает так как надо.

    Добавлено спустя 1 минуту 18 секунд:
    Можете помочь составить регулярное выражение, что бы оно искало текст между { и } но при этом в этом тексте (между { и }) не должно быть {, и я покажу что я имел ввиду.
     
  2. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    Ну так я Вам так и сказал, что первый вариант для простой конструкции где сначала идёт {} а потом текст уже без {}
    А второй вариант как раз под Ваш случай.
    Ок, буду дома - напишу

    Добавлено спустя 5 минут 40 секунд:
    Хотя могу и так прикинуть
    #\{([^\}]+?)\}#

    Добавлено спустя 1 минуту 37 секунд:
    Но тогда ее придётся рекурсивной заменой применить

    Добавлено спустя 56 секунд:
    В callback после каждого найденного вхождения модифицировать строку(заменять {вхождение} на рандомный вариант внутри вхождения) и потом снова рекурсивно регуляркой через callback, но уже с новой строкой... Пока всё не заменится

    Добавлено спустя 21 минуту 38 секунд:
    Но это уже искусственное усложнение

    Добавлено спустя 13 минут 37 секунд:
    Ничего удивительного, т.к. это сокращенный вариант первого варианта, а как я уже говорил ранее:
     
  3. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Код (PHP):
    1. function xxx($str) {
    2.     
    3.     $fns = function($data) {
    4.         $temp = explode('|', $data[1]);
    5.         return $temp[ rand(0, sizeof($temp)-1 ) ];
    6.     };
    7.     
    8.     while ( strpos($str, '{') !== false ) {
    9.         $str = preg_replace_callback('/\{([^\{]+?)\}/sui', $fns, $str);
    10.     }        
    11.     
    12.     return $str;
    13. }
    14.  
    15.  
    16. echo( '<div>'. xxx('Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела') .'</div>' ); 
    Я не так глуп как выгляжу :)
     
  4. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    сравнение моего и Вашего варианта на более объемном примере:
    Код (PHP):
    1. function xxx($str) {
    2.  
    3.     $fns = function($data) {
    4.         $temp = explode('|', $data[1]);
    5.         return $temp[ rand(0, sizeof($temp)-1 ) ];
    6.     };
    7.     
    8.     while (true) {
    9.         if ( strpos($str, '{') === false ) {
    10.             break;
    11.         }
    12.         $str = preg_replace_callback('/\{([^\{]+?)\}/sui', $fns, $str);
    13.     }
    14.         
    15.     
    16.     return $str;
    17. }
    18.  
    19. $start = microtime(true);
    20. $str = "{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в175}}|{в6|в7}} александр {{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в156}}|{в6|в7}} дмитрий";
    21. foreach(preg_split('#[^\|\{\}]*(\{[\s\S]+?\}[^\|\{\}]+)#', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY) as $entry)
    22. {
    23.     $end_pos = strrpos($entry, '}');
    24.     $before = substr($entry, 0, $end_pos);
    25.     $end = substr($entry, $end_pos+(substr($entry, $end_pos, 1)=='}'?1:0));
    26.     $before = str_replace(array('}','{'), '', $before);
    27.     $arr = explode('|', $before);
    28.     $str = str_replace($entry, $arr[array_rand($arr)].$end, $str);
    29. }
    30. echo $str.'<br>';
    31. echo number_format(microtime(true)-$start, 6).'<br><br>';
    32. //=============================================
    33. $start = microtime(true);
    34. echo( '<div>'. xxx('{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в175}}|{в6|в7}} александр {{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в156}}|{в6|в7}} дмитрий') .'</div>' );
    35. echo number_format(microtime(true)-$start, 6); 
    выдает:
    Добавлено спустя 1 минуту 32 секунды:
    а теперь засуньте туда пару статей :)

    Добавлено спустя 1 минуту 42 секунды:
    говорю же - не нужна тут такая рекурсия

    Добавлено спустя 6 минут 42 секунды:
    и модицикаторы sui в регулярке не нужны
    s(определяет символ . как набор любых символов(включая перевод строки)) - не нужно потому что символ . не используется в данной регулярке
    u(обработка как utf8) - не нужно в том случае если у Вас включена перегрузка функций mb_string
    i(игнорировать регистр символов) - не нужно тк у Вас в регулярке нет букв

    Добавлено спустя 5 минут 33 секунды:
    вместо
    Код (Text):
    1. rand(0, sizeof($temp)-1 )
    можно просто написать
    Код (Text):
    1. array_rand($temp)
     
  5. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    странная вещь, если брать мелкое предложение и запускать функцию много раз, тогда да, моё творение работает раза в 2 медленнее, а вот если на оборот, взять текст по больше и запускать функцию всего пару раз, то на оборот моё работает быстрее, может я где то накосорезил?

    Код (PHP):
    1. function xxx($str) {
    2.     
    3.     $fns = function($data) {
    4.         $temp = explode('|', $data[1]);
    5.         return $temp[ rand(0, sizeof($temp)-1 ) ];
    6.     };
    7.     
    8.     while ( strpos($str, '{') !== false ) {
    9.         $str = preg_replace_callback('/\{([^\{]+?)\}/', $fns, $str);
    10.     }        
    11.     
    12.     return $str;
    13. }
    14.  
    15. function xxx2 ($str) {
    16.     
    17.     foreach(preg_split('#[^\|\{\}]*(\{[\s\S]+?\}[^\|\{\}]+)#', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY) as $entry)
    18. {
    19.     $end_pos = strrpos($entry, '}');
    20.     $before = substr($entry, 0, $end_pos);
    21.     $end = substr($entry, $end_pos+(substr($entry, $end_pos, 1)=='}'?1:0));
    22.     $before = str_replace(array('}','{'), '', $before);
    23.     $arr = explode('|', $before);
    24.     $str = str_replace($entry, $arr[array_rand($arr)].$end, $str);
    25. }
    26.  
    27. return $str;
    28. }
    29.  
    30.  
    31. function test_time($fns) {
    32.  
    33. $str = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела';
    34. $new_str = '';
    35. for ( $i = 0; $i < 1000; $i++  ) { $new_str .= {$str}"; }
    36.  
    37. $start = microtime();
    38.  
    39. for ( $i = 0; $i < 5; $i++ ) { $fns($new_str); }
    40.  
    41. $end = microtime();
    42. $result = $end - $start;
    43. echo( "<h3>Потрачено времени: {$result}</h3>" );      
    44. }
    45.  
    46.  
    47. echo( "<h2>xxx:</h2>" ); 
    48. test_time('xxx');
    49.  
    50. echo( "<h2>xxx2:</h2>" ); 
    51. test_time('xxx2'); 
    PS текст 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела' складывается 1000 раз и он отправляется в функцию.
     
  6. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    потому что текст после повторени получается однородный, а движок регулярок неплохо работает с однородным текстом(в реальности-то вряд ли текст будет однородный), но даже в этом случае есть вариант БЕЗ рекурсий....
    вот вариант сравнения через preg_replace_callback БЕЗ рекурсий(моем варианте)
    обратите внимание как реализовано повторение строки(цикл здесь не нужен)
    Код (PHP):
    1. function xxx($str) {
    2.  
    3.     $fns = function($data) {
    4.         $temp = explode('|', $data[1]);
    5.         return $temp[ rand(0, sizeof($temp)-1 ) ];
    6.     };
    7.     
    8.     while (true) {
    9.         if ( strpos($str, '{') === false ) {
    10.             break;
    11.         }
    12.         $str = preg_replace_callback('/\{([^\{]+?)\}/sui', $fns, $str);
    13.     }
    14.         
    15.     
    16.     return $str;
    17. }
    18.  
    19. //$source = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела';
    20. $source = '{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в175}}|{в6|в7}} александр {{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в156}}|{в6|в7}} дмитрий';
    21. $source = str_repeat($source, 1000);
    22. $start = microtime(true);
    23. $str = $source;
    24. $str = preg_replace_callback('#(\{[\s\S]+?\})([^\|\{\}]+)#', function($mathces)
    25. {
    26.     $mathces[1] = str_replace(array('}','{'), '', $mathces[1]);
    27.     $arr = explode('|', $mathces[1]);
    28.     return $arr[array_rand($arr)].$mathces[2]; 
    29. }, $str);
    30. echo $str.'<br>';
    31. echo number_format(microtime(true)-$start, 6).'<br><br>';
    32. //=============================================
    33. $start = microtime(true);
    34. echo( '<div>'. xxx($source) .'</div>' );
    35. echo number_format(microtime(true)-$start, 6); 
    для строки
    x1000
    и для строки
    x1000
    Добавлено спустя 3 минуты 26 секунд:
    тот же тест для строк без повторений в 1000 раз
    для
    для
     
  7. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    хорошо, спасибо, вы пополнили копилку моих знаний.
     
  8. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    обращайтесь ;)
     
  9. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    Посмотрите, я еще усовершенствовал свой вариант.... Теперь, если внутри текста и вариантов надо вывести символ { или } или |, то его всего лишь надо заэкранировать... посмотрите пример... думаю многим будет интересно....
    Код (PHP):
    1. function xxx($str) {
    2.  
    3.     $fns = function($data) {
    4.         $temp = explode('|', $data[1]);
    5.         return $temp[ rand(0, sizeof($temp)-1 ) ];
    6.     };
    7.     
    8.     while (true) {
    9.         if ( strpos($str, '{') === false ) {
    10.             break;
    11.         }
    12.         $str = preg_replace_callback('/\{([^\{]+?)\}/sui', $fns, $str);
    13.     }
    14.         
    15.     
    16.     return $str;
    17. }
    18.  
    19. $source = 'В языке {{C++|C}|{JavaScript|PHP}|C#|Java} блоки кода можно объединять в фигурные скобки, например \{{ВАШ КОД|КАКОЙ-ТО КОД};\}<br>Условия записываются так {if(1)|if(1\|\|0)}{\{do_something();\}|\{do_some_work();\}}';
    20. $start = microtime(true);
    21. $str = $source;
    22. $str = preg_replace_callback('#(?<!\\\)(\{[\s\S]+?(?<!\\\)\})(?![\|\}])#', function($mathces)
    23. {
    24.     $mathces[1] = preg_replace('#(?<!\\\)\{|(?<!\\\)\}#', '', $mathces[1]);
    25.     $arr = preg_split('#(?<!\\\)\|#', $mathces[1], -1,PREG_SPLIT_NO_EMPTY);
    26.     return preg_replace('#(?<!\\\)\\\#', '',$arr[array_rand($arr)]); 
    27. }, $str);
    28. echo str_replace(array('\{', '\}'), array('{', '}'), $str).'<br>';
    29. echo number_format(microtime(true)-$start, 6).'<br><br>';
    30. //=============================================
    31. $start = microtime(true);
    32. echo( '<div>'. xxx($source) .'</div>' );
    33. echo number_format(microtime(true)-$start, 6);
    выдаст
    Ваш вариант вообще покрамсал {, } и |...
    да, разница во времени сократилась, но согласитесь, приятнее всетаки иметь возможность использовать внутри вариантов символы {, } и | (которые Ваш вариант просто съедает) ;)
    теперь тот же текст, только умноженный на 50,000 раз
    вариант с поддержкой {, } и | в тексте
    вариант без поддржки {, } и | в тексте
    Добавлено спустя 9 минут 57 секунд:
    хотя в случае с короткими фразами, мой вариант с поддержкой {, } и | в тексте занимает больше времени:
    обусловлено это дополнительной нагрузкой на регулярку так называемыми утверждениями, ну и добавлением preg_split'ов, как Вы можете видеть.
    но в варинте без поддержки {, } и | в тексте, мой вариант всетаки быстрее и на коротких фразах :)
    Добавлено спустя 12 минут 38 секунд:
    если Вам понадобится использовать пустые варианты например
    то просто не используйте PREG_SPLIT_NO_EMPTY при вызове функции preg_split


    на всякий случай вырежу сам код и опишу плюсы и минусы
    вариант без поддержки {, } и | в тексте
    Код (PHP):
    1. $str = preg_replace_callback('#(\{[\s\S]+?\})([^\|\{\}]+)#', function($mathces)
    2. {
    3.     $mathces[1] = str_replace(array('}','{'), '', $mathces[1]);
    4.     $arr = explode('|', $mathces[1]);
    5.     return $arr[array_rand($arr)].$mathces[2]; 
    6. }, $str);
    7.  $str.'<br>';
    плюсы:
    - высокая скорость на любых объемах
    - поддержка любых форматов текста(с очень небольшой оговоркой)
    минусы:
    - не поддерживает знаки {, } и | внутри текста
    - оговорка 1: между рядом стоящими {...}{...} нужно вставлять хотя бы пробел. оговорка 2: в конце текста надо вставлять пробел

    вариант с поддержкой {, } и | в тексте
    Код (PHP):
    1. $str = preg_replace_callback('#(?<!\\\)(\{[\s\S]+?(?<!\\\)\})(?![\|\}])#', function($mathces)
    2. {
    3.     $mathces[1] = preg_replace('#(?<!\\\)\{|(?<!\\\)\}#', '', $mathces[1]);
    4.     $arr = preg_split('#(?<!\\\)\|#', $mathces[1], -1,PREG_SPLIT_NO_EMPTY);
    5.     return preg_replace('#(?<!\\\)\\\#', '',$arr[array_rand($arr)]); 
    6. }, $str);
    7. echo str_replace(array('\{', '\}'), array('{', '}'), $str).'<br>'; 
    плюсы:
    - высокая скорость на больших объемах
    - поддерживает знаки {, } и | внутри текста
    - поддерживает любой формат текста(даже рядом стоящие {...}{...})
    минусы:
    - маленькая скорость на мелких выражениях

    в нашей сфере всегда приходится выбирать между чем-то...

    фуф... ну вот как-то так....
     
  10. smitt

    smitt Старожил

    С нами с:
    3 янв 2012
    Сообщения:
    3.166
    Симпатии:
    65
    Товарищ s.melukov позвольте но мне кажется вы сами себе противоречите.
    Начнем по порядку:
    1.
    Код (PHP):
    1. function xxx($str) {
    2.  
    3.     $fns = function($data) {
    4.         $temp = explode('|', $data[1]);
    5.         return $temp[ rand(0, sizeof($temp)-1 ) ];
    6.     };
    7.     
    8.     while (true) {
    9.         if ( strpos($str, '{') === false ) {
    10.             break;
    11.         }
    12.         $str = preg_replace_callback('/\{([^\{]+?)\}/sui', $fns, $str);
    13.     }
    14.         
    15.     
    16.     return $str;
    17. }
    18.  
    19. //$source = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела';
    20. $source = '{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в175}}|{в6|в7}} александр {{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в156}}|{в6|в7}} дмитрий';
    21. $source = str_repeat($source, 1000);
    22. $start = microtime(true);
    23. $str = $source;
    24. $str = preg_replace_callback('#(\{[\s\S]+?\})([^\|\{\}]+)#', function($mathces)
    25. {
    26.     $mathces[1] = str_replace(array('}','{'), '', $mathces[1]);
    27.     $arr = explode('|', $mathces[1]);
    28.     return $arr[array_rand($arr)].$mathces[2]; 
    29. }, $str);
    30. echo $str.'<br>';
    31. echo number_format(microtime(true)-$start, 6).'<br><br>';
    32. //=============================================
    33. $start = microtime(true);
    34. echo( '<div>'. xxx($source) .'</div>' );
    35. echo number_format(microtime(true)-$start, 6); 
    36.  
    Чем он принципиально отличается от моего варианта? Точно так же вы регуляркой с колбеком обрабатываете, я регуляркой очищаю от {} правда как помню 1 оставался поэтому тримил вы же их просто реплайс делаете. В чем выигрышь производительности, вы так долго мучались.

    2. Ваш окончательный вариант содержит 3 регулярки а по вашему утверждению регулярка зло которое сильно тормозит.
    Я не считаю их злом а в некоторых случаях что бы не плодить километры кода они незаменимы. Просто интересно с чем связано отказ от варианта без регулярок?
     
  11. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    да, давайте разберемся
    1)
    последний вариант который Вы предложили - вот
    Код (PHP):
    1. function getRandomAnswer($data){
    2. $answers = explode('|', $data[1]);
    3. return $answers[rand(0, count($answers) -1)];
    4. }
    5.  
    6. $str = "{{Привет|Здравствуйте|Добрый день} Александр!|{Хороший|Великолепный} день Александр!}";
    7. $rand_answers = preg_replace_callback('/{+(.*?)}+/', 'getRandomAnswer', $str);
    8. $answer = explode("|", $rand_answers);
    9. echo trim($answer[rand(0, count($answer) -1)], '}');
    давайте скормим ему строку
    да, отработает нормально, но меня смутила регулярка, ведь в данном случае можно обойтись без нее, поэтому я и предложил вариант без регулярки
    Код (PHP):
    1. $str = "{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в15}}|{в6|в7}} александр";
    2. $end_pos = strrpos($str, '}');
    3. $before = substr($str, 0, $end_pos);
    4. $end = substr($str, $end_pos+(substr($str, $end_pos, 1)=='}'?1:0));
    5. $before = str_replace(array('}','{'), '', $before);
    6. $arr = explode('|', $before);
    7. echo $arr[array_rand($arr)].$end;
    да, отличается только отсутствием регулярки, тк она тут и не нужна....
    давайте скормим моему и Вашему варианту строку
    но если скормить и моему и Вашему варианту строку
    то и мой и Ваш сожрет бОльшую часть строки
    именно поэтому я далее написал, что если хочется чего-то более сложного, то да, нужна регулярка и привел следующий пример
    Код (PHP):
    1. $str = preg_replace_callback('#(\{[\s\S]+?\})([^\|\{\}]+)#', function($mathces)
    2. {
    3.     $mathces[1] = str_replace(array('}','{'), '', $mathces[1]);
    4.     $arr = explode('|', $mathces[1]);
    5.     return $arr[array_rand($arr)].$mathces[2]; 
    6. }, $str);
    7. echo $str;
    тут уже нет привязки к позиции и количеству {} относительно текста
    далее я, немного подумав, решил ввести поддержку {}| прямо в тексте и предложил такой вариант
    Код (PHP):
    1. $str = preg_replace_callback('#(?<!\\\)(\{[\s\S]+?(?<!\\\)\})(?![\|\}])#', function($mathces)
    2. {
    3.     $mathces[1] = preg_replace('#(?<!\\\)\{|(?<!\\\)\}#', '', $mathces[1]);
    4.     $arr = preg_split('#(?<!\\\)\|#', $mathces[1], -1,PREG_SPLIT_NO_EMPTY);
    5.     return preg_replace('#(?<!\\\)\\\#', '',$arr[array_rand($arr)]); 
    6. }, $str);
    7. echo str_replace(array('\{', '\}'), array('{', '}'), $str).'<br>';
    тут вообще нет привязки ни к позиции {} ни к их количеству и можно использовать {}| в тексте
    как видите, чем больше условий, тем больш используются регулярки
    2)
    я ни в коем случае не говорю что регулярки это зло.
    я люблю регулярки, просто считаю что их не нужно использовать там где можно обойтись и без них
    так что всё логично :)
     
  12. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    Код (PHP):
    1. function getRandomAnswer($data){
    2. $answers = explode('|', $data[1]);
    3. return $answers[rand(0, count($answers) -1)];
    4. }
    5.  
    6. $str = "{{Привет|Здравствуйте|Добрый день} Александр!|{Хороший|Великолепный} день Александр!}";
    7. $rand_answers = preg_replace_callback('/{+(.*?)}+/', 'getRandomAnswer', $str);
    8. $answer = explode("|", $rand_answers);
    9. echo trim($answer[rand(0, count($answer) -1)], '}'); 
    вот это работает не верно (в принципе по этому я писал что не понимаю как оно работает и будут над этим думать)

    есть взять такую строчку:
    Код (PHP):
    1. $str = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела'; 
    то часть кода жрет, т.е. выводит такое:
    а где как дела? все что не попадает между { и } должно быть в тексте.
     
  13. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    ну собственно я это и расписал в предыдущем посте
     
  14. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    ОХ и памяти сожрет...
     
  15. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    до собственно любое мероприятие по парсингу чего-либо жрет памяти больше чем привыкли )
    и это еще не полноценный лексический анализатор(с проверкой на правильность синтаксиса, разбором на лексемы и тд и тп) :)))
    поэтому и предложено несколько вприантов
    плюс ко всему, строка перебирается не php-конструкциями типа while, for и тд, а нативной C-шной библиотекой регулярок, поэтому тут уже расход памяти зависит только от правильно составленной регулярки и количества текста который надо обработать
     
  16. smitt

    smitt Старожил

    С нами с:
    3 янв 2012
    Сообщения:
    3.166
    Симпатии:
    65
    Бугага:)
    VLK если хочешь выжить в мире программирования учись думать а не копировать! Копирование приводит к плохим результатам.
    Ты вообще то не понимал как работать с preg_replace_callback как его здесь можно применить, я не думал 2 дня не оптимизировал я для примера в онлайн редакторе накидал код для парсинга твоего первоначального примера и он работает. Дал бы тот что с как {твои|ваши} дела может я пошел бы другим путем. Цель у меня была не написать и продумать детали за тебя а дать толчек что ты начал думать и писать самостоятельно.

    Да ладно я не в упрек написал, просто вы так начали хорошо, регулярки плохо сейчас без них напишу а в результате 3 регулярке в конечном варианте. Вот я немного и разочаровался.
     
  17. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    ну так я и написал без регулярок для простого варианта текста(аналог Вашего варианта)
     
  18. smitt

    smitt Старожил

    С нами с:
    3 янв 2012
    Сообщения:
    3.166
    Симпатии:
    65
    Хмм, давай начнем с того что требовалось сделать через регулярку, да и что говорить сами понимаете что это легче сделать через регулярные выражения а не плодить кучу кода, к чему в конечном счете вы и пришли.
    Ну я думаю от одной регулярки ничего ужасного не произойдет, мы же не парсим Войну и Мир, не тестировал но на среднем тексте думаю разница будет не сильно заметна между моим кодом и твоим без регулярок.

    Но в итоге признайтесь ваш вариант с 4 регулярками а на деле вызываться будет гораздо больше раз ну с точки зрения бестродействия как то не очень.
    В том случае где я использовал считаю не критичным.
     
  19. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    5 строк кода это куча кода?

    я же сказал, что каждый враиант заточен под свою задачу
    первый вариант без регулярок(аналог Вашему) - под совсем простые предложения
    работает быстро, жрет мало, но минус в том, что он не гибкий

    второй вариант с регулярками - для нескольких вхождений {...} в строке с любой глубиной
    работает быстро, но до сих пор не поддерживает {}| в тексте

    третий вариант с тоже с регулярками - позволяет обрабатывать любую последовательность и поддерживает {}| в тексте
    да, занимает больше времени и памяти за счет того, что может больше чем предыдущие 2 варианта

    началось-то всё с того, что я просто предложил вариант аналогичный Вашему, но без регулярок вот и всё
     
  20. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    а может кто отдельно варианты привести вместе с тестовой фразой?
     
  21. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    вот моих 2 варианта:
    вариант без поддержки {, } и | в тексте
    Код (PHP):
    1. $str = preg_replace_callback('#(\{[\s\S]+?\})([^\|\{\}]+)#', function($mathces)
    2. {
    3.     $mathces[1] = str_replace(array('}','{'), '', $mathces[1]);
    4.     $arr = explode('|', $mathces[1]);
    5.     return $arr[array_rand($arr)].$mathces[2]; 
    6. }, $str);
    7.  $str.'<br>';
    плюсы:
    - высокая скорость на любых объемах
    - поддержка любых форматов текста(с очень небольшой оговоркой)
    минусы:
    - не поддерживает знаки {, } и | внутри текста
    - оговорка 1: между рядом стоящими {...}{...} нужно вставлять хотя бы пробел. оговорка 2: в конце текста надо вставлять пробел

    вариант с поддержкой {, } и | в тексте
    Код (PHP):
    1. $str = preg_replace_callback('#(?<!\\\)(\{[\s\S]+?(?<!\\\)\})(?![\|\}])#', function($mathces)
    2. {
    3.     $mathces[1] = preg_replace('#(?<!\\\)\{|(?<!\\\)\}#', '', $mathces[1]);
    4.     $arr = preg_split('#(?<!\\\)\|#', $mathces[1], -1,PREG_SPLIT_NO_EMPTY);
    5.     return preg_replace('#(?<!\\\)\\\#', '',$arr[array_rand($arr)]); 
    6. }, $str);
    7. echo str_replace(array('\{', '\}'), array('{', '}'), $str).'<br>'; 
    плюсы:
    - высокая скорость на больших объемах
    - поддерживает знаки {, } и | внутри текста
    - поддерживает любой формат текста(даже рядом стоящие {...}{...})
    минусы:
    - маленькая скорость на мелких выражениях

    вот тестовые тексты:
    Код (PHP):
    1. $source = '{Привет|Здравствуйте|Добрый день} Александр!';
    2. $source = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела';
    3. $source = 'В языке {{C++|C}|{JavaScript|PHP}|C#|Java} блоки кода можно объединять в фигурные скобки, например \{{ВАШ КОД|КАКОЙ-ТО КОД};\}<br>Условия записываются так {if(1)|if(1\|\|0)}{\{do_something();\}|\{do_some_work();\}}'; 
     
  22. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    крутяк
     
  23. smitt

    smitt Старожил

    С нами с:
    3 янв 2012
    Сообщения:
    3.166
    Симпатии:
    65
    Я мыслю глобально здесь пять строчек там пять строчек еще где то в итого много кода. Не обращай внимание если я не вижу особой пользы пытаюсь писать поменьше кода.

    Да не напрягайтесь так:) Просто было весело когда я прочитал ваше первое сообщение что регулярки тормозят а в конце увидел вообще жесть:)

    Да что крутого? YSandro считаю правильно предложил а эта куча вложений только все усложняет. До сих пор не понимаю зачем рамдомно выбирать между значениями. Что он там делает хз...
     
  24. s.melukov

    s.melukov Новичок

    С нами с:
    31 июл 2014
    Сообщения:
    78
    Симпатии:
    0
    тогда речь шла про простой вариант текста

    так никто же и не спорит что формат довольно странный(хотя смотря с какой стороны посмотреть), и что при упрощении формата, регулярки и не понадобились бы. но если бы у ТС была возможность упростить формат, он бы так и сделал, я думаю...
    но в данном случае, время бы могло уходить на выборку данных для подстановки. из базы например...

    да нет здесь кучи вложений. тут вызов 5 нативных функций и только в preg_replace_callback есть одного вложение, ито оно не рукерсивное

    ладно, а то сейчас как обычно какой-нибудь холи вар начнется о "правильном" использовании регулярок
     
  25. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    это уже второй вопрос. в случае шаблонного синтаксиса с переменными, надо где-то хранить и откуда-то брать значения этих переменных.