Смотрите, есть текст до обработки, он выглядит так: а после обработки, все что находится в фигурных скобках убирается и за места него вставляется один из вариантов из фигурных скобок в рандомном порядке, т.е. в результате мы получаем: НО! могут быть и более сложные варианты, вложения с вложениями, типа: подскажите, возможно ли подобное организовать через preg_replace или это будет геморройно? как я понимаю нужна регулярное выражение - $pattern, которое будет вытаскивать то, что находится в фигурных скобках, но тут проблема может возникнуть где вложения с вложениями. А в качестве $replacement функция которая из вариантов будет выбрать один и возвращать его, но как передавать туда эти значения.
Я думаю, тут нужна будет рекурсия и функция, которая будет определять, что строка вида "{фраза|фраза}" типа isSupaDupaString(), возвращающая булево значение...
Я лично вижу 3 камня преткновения: 1 - возможно ли составить такое рег. выражение, которое бы искало '{}' при этом что бы в '{}' больше не было '{' т.е. без вложений и разбивало на варианты. 2 - все полученные варианты передавало в функцию и возвращало один из них (как организовать передачу). 3 - как работает preg_replace, начинает ли оно каждый новый перебор с начала или с точки где остановилось, если с самого начала, то все ок, если с точки где остановился раньше - печально. и вроде как можно и без рекурсии обойтись.
нет, тут все правильно, за место слов типа вариант_1_1 могут идти не только слова, а словосочетания, предложения, абзацы и даже целые статьи по 100 000 символов каждая но если Вы предложите вариант получше, буду благодарен
Я не понял более сложный вариант. Там тоже рамдомно надо 1 из 5 выбрать или надо 2 выбрать 1 для первого второй вариант для чего то другого?
распишу более подробно, есть такое: есть две статьи: а в самих статьях идет свое разбитие на такого рода варианты, т.е. допустим статья_1 имеет вид (т.е. за место слова статья_1 там примерно такое, это соответственно укороченный вариант): теперь я надеюсь ясен смысл вложений с вложениями?
Ты сайт пишешь? Сайт это запрос к базе и вывод данных. Вложения в вложении которые могут быть вложенными еще раз 10. Если задумал шаблонизатор написать бери готовый. Давай по другому есть такое {{вариант_1_1|вариант_1_2}|{вариант_2_1|вариант_2_2|вариант_2_3}} Александр! Что должно быть в результате? т.е. нужны входные параметры и то как это должно выглядеть в итоге. Добавлено спустя 7 минут 21 секунду: http://php.ru/manual/function.preg-replace-callback.html
Нет, это не шаблонизатор, я решил сделать спам империю и захватить интернет. Есть 2 текста 1 - {Привет|Здравствуйте|Добрый день} Александр! - вариант_1 2 - {Хороший|Великолепный} день Александр! - вариант_2 объединяем: получаю в итоге, варианты ответа: PS то что текст не несет смысловой нагрузки - это просто примеры, что пришло на ум (да простит господь мой малый словарный запас и скудоумие). задача скрипта он получает такое: а возвращает или выводит на экран один из вариантов ответа выше
Написал по быстрому в онлайн редакторе Код (PHP): function getRandomAnswer($data){ $answers = explode('|', $data[1]); return $answers[rand(0, count($answers) -1)]; } $str = "{{вариант_1_1|вариант_1_2}|{вариант_2_1|вариант_2_2|вариант_2_3}}"; $rand_answers = preg_replace_callback('/{+(.*?)}+/', 'getRandomAnswer', $str); $answer = explode('|', $rand_answers); echo $answer[rand(0, count($answer) -1)]; Добавлено спустя 2 минуты 38 секунд: А вообще можно проще
О_О вот то что и требовалось, только есть одна ошибка, я вставил туда: и кода результат вторая часть т.е.: Хороший день Александр! или Великолепный день Александр! то пишет вместе со знаком '}' т.е.:
Код (PHP): $str = "{{вариант_1_1|вариант_1_2}|{вариант_2_1|вариант_2_2|вариант_2_3}}"; $clean_string = str_replace(array('{', '}',), '', $str); $answers = explode('|', $clean_string); echo $answers[rand(0, count($answers) -1)]; Добавлено спустя 2 минуты 4 секунды: Александра тоже туда засовываешь? Хмм... Мда не ищешь ты легких путей...
используй трим или измени архитектуру или доработай алгоритм. Мож какой то разделитель для поставишь? Добавлено спустя 1 минуту 24 секунды: Ну я дал направление дальше сам думай, может кто то что то посоветует лучшее. Удачи! Добавлено спустя 3 минуты 17 секунд: Зачем все в одну строку засовывать... не ты точно не ищешь легких путей.
Да, большое спасибо, тут осталось только с регулярным выражение разобраться, а точнее его сделать и все будет ок.
Какое еще регулярное выражение((( Код (PHP): function getRandomAnswer($data){ $answers = explode('|', $data[1]); return $answers[rand(0, count($answers) -1)]; } $str = "{{Привет|Здравствуйте|Добрый день} Александр!|{Хороший|Великолепный} день Александр!}"; $rand_answers = preg_replace_callback('/{+(.*?)}+/', 'getRandomAnswer', $str); $answer = explode("|", $rand_answers); echo trim($answer[rand(0, count($answer) -1)], '}'); Добавлено спустя 2 минуты 46 секунд: Посмотрим кто что предложит
ну я сейчас всмотрелся в код и у меня такой же вопрос возник Код работает, только я пока совсем не понимаю как, ну да ладно, буду въезжать, еще раз спасибо.
Такой шаблон не проще было бы сделать так Код (PHP): $str = '{greetings}, {name}!'; , а заменять эти метки функцией из массивов любой сложности? Приветствий может быть больше, на разных языках и т.п. Имён тоже. А то так можно в скобках запутаться (тебе или контент менеджеру), сложно выглядит.
Абсолютно согласен. Рано или поздно он замучиется с многочисленными вложениями. Могу еще изощренней, но и этого пока хватает. Там все просто.
может я конечно не до конца понял суть задачи топикстартера, но зачем всё усложнять? Код (PHP): $str = "{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в15}}|{в6|в7}} александр"; $end_pos = strrpos($str, '}'); $before = substr($str, 0, $end_pos); $end = substr($str, $end_pos+(substr($str, $end_pos, 1)=='}'?1:0)); $before = str_replace(array('}','{'), '', $before); $arr = explode('|', $before); echo $arr[array_rand($arr)].$end; Добавлено спустя 19 минут 59 секунд: если там действительно будет куча статей, то подумайте, сколько времени уйдет на проверку по регулярке Добавлено спустя 23 минуты 32 секунды: а вот если уже совсем хочется извращений(например замена вхождений вне зависимости от позиции {.....}), вот тогда уже регулярки можно использовать Код (PHP): $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}} дмитрий"; foreach(preg_split('#[^\|\{\}]*(\{[\s\S]+?\}[^\|\{\}]+)#', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY) as $entry) { $end_pos = strrpos($entry, '}'); $before = substr($entry, 0, $end_pos); $end = substr($entry, $end_pos+(substr($entry, $end_pos, 1)=='}'?1:0)); $before = str_replace(array('}','{'), '', $before); $arr = explode('|', $before); $str = str_replace($entry, $arr[array_rand($arr)].$end, $str); } echo $str; Добавлено спустя 21 минуту 46 секунд: в последнем примере работают как простые варианты типа: так и более сложные: Добавлено спустя 7 минут 17 секунд: а в первом примере(который без регулярок) подразумевается что после "дмитрий" больше нет {.....}
чуть подправил регулярку Добавлено спустя 8 минут 4 секунды: так тоже работает Добавлено спустя 50 минут 29 секунд: если нужна более сложная логика, уместнее будет просто написать полноценный синтакситечкий анализатор НЕ на регулярках(как вариант, воспользоваться гениратором типа yacc или lex) Добавлено спустя 11 минут 47 секунд: но если всетаки использовать алгоритм с регуляркой, то я рекомендую в конец строки вставлять пробельный символ, чтобы работали вот такие обратные одиночки: Добавлено спустя 10 минут 32 секунды: в общем, подводя итог всему.... первый вариант который я предлагал(без регулярок) подойдет если строка устроена таким образом но не наоборот! но вложенностей может быть любое количество второй вариант(с регуляркой) подойдет почти для любой конфгурации текста, с любым порядком и расположением {...} и текста за исключением между ними должно что-то быть(хотя бы пробел!) например но в любом случае, если используем вариант с регуляркой, не забываем вставлять пробел в конец строки перед обработкой чтобы работали обратки типа
s.melukov я посмотрел, какие то мудреные варианты, то, что предлагает smitt попроще, покороче и как то по логичнее (хотя работает не верно - жрет текст, но ход мысли верный), в чем преимущество ваших вариантов.
по-Вашему, вариант без регулярок и в несколько строк, мудреный? а второй вариант который я предложил(с регулярками) нужен для более сложной логики если Вам важно количество строк, то вот укороченный вариант первого варианта Код (PHP): $str = "{{в1|в2}|{в3|{в10|в11|в12}|{в101|{в222|в333|в444}|в123}|{в13|в14|в15}}|{в6|в7}} александр"; $end = substr($str, strrpos($str, '}')+(substr($str, strrpos($str, '}'), 1)=='}'?1:0)); $arr = explode('|', str_replace(array('}','{'), '', substr($str, 0, strrpos($str, '}')))); echo $arr[array_rand($arr)].$end; по той же логике можно и второй сократить )))) Добавлено спустя 2 минуты 32 секунды: первый без регулярок, а второй позволяет составлять почти любую конфигурацию, хоть в одну строку, хоть в несколько Добавлено спустя 3 минуты 30 секунд: выбирать Вам конечно я предложил, дальше дело Ваше
Код (PHP): $str = 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела'; есть такая строка Стразу может возникнуть вопрос, зачем такое: Код (Text): {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} если можно просто сделать: Код (Text): {Виктор|Антон|Антонио|Антошка|Сергей|Господин|Сэр|Товарищ} Но меня интересует вариант работы именно с таким текстом: Код (Text): {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} где вложения во вложениях и вложениями погоняют Я сейчас не могу забацать решение т.к. конструктор регулярных выражений не работает ( http://php-include.ru/regulyarnye-vyrazheniya-onlain ) (вот именно сегодня что то оно не пашет) Как я вижу логику работы: Мы при помощи preg_replace_callback ищем текст который находится между { и } при этом между { и } не должно быть { т.е. без вложений, после чего найденное включая знаки { и } отправляем callback, а оно возвращает что то конкретное т.е. вот так вот: из 'Привет {{Виктор|{Антон|Антонио|Антошка}|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела' находит {Антон|Антонио|Антошка} и возвращает допустим Антонио, в итоге отредактированный текст выглядит уже так: 'Привет {{Виктор|Антонио|Сергей}|{Господин|Сэр|Товарищ}} как {твои|ваши} дела' далее находит {Виктор|Антонио|Сергей} и выбирает допустим Сергей, текст выглядит уже так: 'Привет {Сергей|{Господин|Сэр|Товарищ}} как {твои|ваши} дела' потом находит {Господин|Сэр|Товарищ} и выбирает Товарищ, в итоге текст выглядит так: 'Привет {Сергей|Товарищ} как {твои|ваши} дела' ну а потом выбирает Товарищ и ваши и в конечный результат: 'Привет Товарищ как ваши дела' PS тут всего один принципиальный вопрос, будет ли так как надо работать preg_replace_callback все же первый вариант без вложений {Антон|Антонио|Антошка} по позиции будет находиться позже тем более поздний {Сергей|Товарищ}.
Ну так и чем Вас мой вариант не устраивает? Ох не понимаю я зачем Вы всё усложняете оперируя рекурсивным алгоритмами если всё что Вы сейчас описали проще сказать так: нужно выбирать рандомный вариант из {...} с вложениями вложений в относительной независимости от позиции и количества {...}..... Поэтому мой вопрос тот же - чем мои варианты противоречат описанной Вами логике? Добавлено спустя 2 минуты 10 секунд: Давайте попробуем так... Скормите Ваш пример варианту с регулярками и давайте посмотрим что получится, Вы скажете что Вас не устраивает и уже оттуда будем плясать. Я просто сейчас вне дома и под рукой нет php поэтому не могу сам проверить[/quote]