Как генерировать случайные строки, соответствующие заданному регулярному выражению?

дублирую:

случайная строка, которая соответствует регулярному выражению

нет, это не так. Я ищу простой и универсальный метод, который я мог бы фактически реализовать. Это намного сложнее, чем случайное генерирование паролей.


Я хочу создать приложение, которое принимает регулярное выражение и показывает 10 случайно сгенерированных строк, соответствующих этому выражению. Это должно помочь людям лучше понять их regexps, и решить, т. е. если они достаточно безопасны для целей проверки. Кто-нибудь знает простой способ сделать это?

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

повторяю, я ищу легкий и универсальный способ сделать это.

Edit: подход грубой силы не может быть и речи. Предполагая, что случайные строки будут просто [a-z0-9]{10} и 1 млн. итерации в секунду, это займет 65 лет для итерации через пространство всех 10-символьных строк.

5 ответов


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

Это не работает для "регулярных" выражений, которые на самом деле не являются регулярными, хотя, например, выражения с backreferences. Это зависит от того, какого рода выражение вы ищете.


взгляните на Perl String:: Random.


одно довольно уродливое решение, которое может быть или не быть практичным, - использовать существующий вариант диагностики регулярных выражений. Некоторые библиотеки регулярных выражений имеют возможность выяснить, где регулярное выражение не совпало. В этом случае, вы может используйте то, что по сути является формой грубой силы, но используя один символ за раз и пытаясь получить более длинные (и далее соответствующие) строки, пока не получите полное совпадение. Это очень уродливое решение. Однако, не похож на стандартное разрешение грубой силы, оно сбой в такой строке, как ab, также скажет вам, Существует ли строка ab.* который будет соответствовать (если нет, остановитесь и попробуйте ac. Если да, попробуйте длинную строку). Это наверное не осуществимо с все regex библиотеки.

с другой стороны, такое решение, наверное, очень круто с точки зрения преподавания. На практике это, вероятно, похоже на решение dfa, но без требования думать о dfas.

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


Если ваши единственные критерии заключаются в том, что ваш метод прост и универсален, то нет ничего проще или универсальнее грубой силы. :)

for (i = 0; i < 10; ++i) {
    do {
        var str = generateRandomString();
    } while (!myRegex.match(str));
    myListOfGoodStrings.push(str);
}

конечно, это очень глупо способ делать вещи, и в основном подразумевалось как шутка.

Я думаю, что лучше всего было бы попробовать написать свой собственный очень простой парсер, обучая его только тем вещам, с которыми вы ожидаете столкнуться (например: диапазоны букв и чисел, повторяющиеся/необязательные символы... Не беспокоиться по поводу зады и т. д.)


критерий универсальности невозможно. Учитывая регулярное выражение "^быть или не быть -- вот в чем вопрос:$" не будет десять уникальных случайных строк, которые соответствуют.

для невырожденных случаях:

ссылка moonshadow на строку Perl:: Random-это ответ. Программа Perl, которая считывает регулярное выражение из stdin и записывает вывод из десяти вызовов String::Random в stdout, тривиальна. Скомпилируйте его либо в Windows, либо в Unix exe с Perl2exe и вызвать его из PHP, Python или что-то еще.

см. Также генератор случайных текстов на основе regex