Спинтакс на PHP и JavaScript с поддержкой вложенных конструкций
Иногда возникает задача автоматически генерировать разные варианты текста из одного шаблона. Например, для объявлений, 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-рассылки;
- тестовые данные;
- шаблоны сообщений;
- промпты для ИИ;
- любые повторяющиеся текстовые заготовки.
Спинтакс удобен, когда нужно быстро получить много вариантов текста из одного шаблона. Главное — не злоупотреблять слишком сложными вложенными конструкциями, иначе шаблон станет тяжело читать и поддерживать.
Если использовать такие маски аккуратно, можно заметно ускорить подготовку объявлений, описаний и других шаблонных текстов без ручного переписывания каждого варианта.
Комментарии
Будем рады вашему мнению и вопросам по статье.