Главная страница / Блог / Спинтакс на PHP и JavaScript с поддержкой вложенных конструкций
PHP Dev

Спинтакс на PHP и JavaScript с поддержкой вложенных конструкций

2 июля 2026 10 минут чтения 2375 просмотров

Иногда возникает задача автоматически генерировать разные варианты текста из одного шаблона. Например, для объявлений, SEO-текстов, описаний товаров, e-mail-рассылок, тестовых данных или любых других шаблонных материалов.

Для таких задач удобно использовать спинтакс — специальный синтаксис, который позволяет случайным образом выбирать слова, фразы или целые блоки текста.

Изначально я писал этот код для генерации объявлений на Авито, но в итоге решение получилось более универсальным. Его можно использовать практически в любом проекте, где нужно быстро получать разные варианты текста.

Какие маски поддерживаются

В примере используются два типа масок.

Случайный выбор одного варианта

{привет|здравствуйте|добрый день}

Из такой конструкции будет выбран только один случайный вариант.

Перемешивание всех элементов

[солнце,&море,&облака]

В этом случае будут выведены все элементы, но каждый раз в случайном порядке.

Например:

море солнце облака

или:

облака море солнце

Вложенные конструкции

Обе маски поддерживают вложенность. Это позволяет собирать более сложные шаблоны и получать большое количество вариантов из одного текста.

{Привет|Здравствуйте|Добрый день}, [солнце,&{море|река},&облака]

Главное — внимательно следить за скобками. Если где-то забыть закрывающую скобку, результат может получиться неожиданным.

Реализация на PHP

Ниже более аккуратная версия функции. Она обрабатывает вложенные конструкции, не заменяет случайно одинаковые блоки по всему тексту и отдельно чистит лишние пробелы.

function spinText(string $text): string
{
    $text = preg_replace('/\r\n|\r|\n|\t/', '', $text);

    while (preg_match('/\{([^{}]*)\}/', $text, $match)) {
        $options = array_map('trim', explode('|', $match[1]));
        $selected = $options[array_rand($options)];

        $text = preg_replace(
            '/' . preg_quote($match[0], '/') . '/',
            $selected,
            $text,
            1
        );
    }

    while (preg_match('/\[([^\[\]]*)\]/', $text, $match)) {
        $items = array_map('trim', explode('&', $match[1]));
        shuffle($items);

        $selected = implode(' ', $items);
        $selected = preg_replace('/[;,]\s*$/', '', $selected);

        $text = preg_replace(
            '/' . preg_quote($match[0], '/') . '/',
            $selected,
            $text,
            1
        );
    }

    $text = str_replace('amp;', '', $text);
    $text = preg_replace('/\s+/', ' ', $text);
    $text = str_replace(' ,', ',', $text);
    $text = str_replace(' .', '.', $text);
    $text = str_replace(' !', '!', $text);
    $text = str_replace(' ?', '?', $text);

    return trim($text);
}

Пример использования

$template = "{Привет|Здравствуйте|Добрый день}!

Сегодня у нас [солнце,&море,&облака].

Желаем {хорошего дня|отличного настроения|приятных покупок}.";

echo spinText($template);

На выходе каждый раз будет получаться немного другой текст.

  • удаляет переносы строк и табуляцию;
  • обрабатывает конструкции {...} со случайным выбором одного варианта;
  • обрабатывает конструкции [...] с перемешиванием всех элементов;
  • поддерживает вложенные конструкции;
  • удаляет лишние пробелы;
  • исправляет пробелы перед знаками препинания;
  • удаляет артефакт amp;, который иногда появляется после HTML-редакторов.

Версия на JavaScript

Аналогичная функция на JavaScript:

function spinText(text) {
    text = text.replace(/\r\n|\r|\n|\t/g, '');

    let match;

    while ((match = text.match(/\{([^{}]*)\}/))) {
        const options = match[1]
            .split('|')
            .map(option => option.trim());

        const selected = options[Math.floor(Math.random() * options.length)];

        text = text.replace(match[0], selected);
    }

    while ((match = text.match(/\[([^\[\]]*)\]/))) {
        const items = match[1]
            .split('&')
            .map(item => item.trim());

        for (let i = items.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [items[i], items[j]] = [items[j], items[i]];
        }

        let selected = items.join(' ');
        selected = selected.replace(/[;,]\s*$/, '');

        text = text.replace(match[0], selected);
    }

    text = text.replace(/amp;/g, '');
    text = text.replace(/\s+/g, ' ');
    text = text.replace(/\s+([,.!?])/g, '$1');

    return text.trim();
}

Пример на JavaScript

const template = "{Привет|Здравствуйте|Добрый день}! Сегодня у нас [солнце,&море,&облака].";

console.log(spinText(template));

Где можно использовать

  • генерация объявлений;
  • описания товаров;
  • SEO-тексты;
  • e-mail-рассылки;
  • тестовые данные;
  • шаблоны сообщений;
  • промпты для ИИ;
  • любые повторяющиеся текстовые заготовки.

Спинтакс удобен, когда нужно быстро получить много вариантов текста из одного шаблона. Главное — не злоупотреблять слишком сложными вложенными конструкциями, иначе шаблон станет тяжело читать и поддерживать.

Если использовать такие маски аккуратно, можно заметно ускорить подготовку объявлений, описаний и других шаблонных текстов без ручного переписывания каждого варианта.

Комментарии

Будем рады вашему мнению и вопросам по статье.