Создайте программу, которая вводит регулярное выражение и выводит строки, которые удовлетворяют этому регулярному выражению
Я думаю, что название точно суммирует мой вопрос, а просто немного уточняет.
Вместо того, чтобы использовать регулярное выражение для проверки свойств существующих строк, я хотел бы использовать регулярное выражение как способ генерации строк, обладающих определенными свойствами.
Примечание. Функция не должна генерировать каждую строку, которая удовлетворяет регулярному выражению (потому что это будет бесконечное число строк для большого количества регулярных выражений). Достаточно выборки из многих допустимых строк.
Насколько это возможно? Если решение слишком сложное/большое, я доволен общей дискуссией/схемой. Кроме того, меня интересуют любые существующие программы или библиотеки (.NET), которые это делают.
Ответы
Ответ 1
Хорошо регулярное выражение конвертируется в DFA, который можно рассматривать как график. Чтобы сгенерировать строку с учетом этого DFA-графа, вы просто найдете путь от состояния начала до конечного состояния. Вам просто нужно подумать о том, как вы хотите обрабатывать циклы (возможно, по крайней мере один раз, чтобы получить выборку? N раз?), Но я не понимаю, почему это не сработает.
Ответ 2
Это можно сделать с помощью обхода DFA (включая псевдокод), либо путем простого изменения дерева абстрактного синтаксиса регулярного выражения или преобразования в NFA сначала, как объясняется Дуг Макилрой: бумага и код Haskell. (Он считает, что подход NFA работает быстрее, но он не сравнивал его с DFA.)
Все они работают с регулярными выражениями без обратных ссылок, то есть "реальными" регулярными выражениями, а не регулярными выражениями Perl. Чтобы обработать дополнительные функции Perl, было бы проще добавить на постфильтр.
Добавлено: код для этого в Python, Питер Норвиг и я.
Ответ 3
Эта утилита на UtilityMill инвертирует некоторое простое регулярное выражение. Он основан на этом примере из вики-страницы pyparsing. Тесты для этой программы:
[A-EA]
[A-D]*
[A-D]{3}
X[A-C]{3}Y
X[A-C]{3}\(
X\d
foobar\d\d
foobar{2}
foobar{2,9}
fooba[rz]{2}
(foobar){2}
([01]\d)|(2[0-5])
([01]\d\d)|(2[0-4]\d)|(25[0-5])
[A-C]{1,2}
[A-C]{0,3}
[A-C]\s[A-C]\s[A-C]
[A-C]\s?[A-C][A-C]
[A-C]\s([A-C][A-C])
[A-C]\s([A-C][A-C])?
[A-C]{2}\d{2}
@|TH[12]
@(@|TH[12])?
@(@|TH[12]|AL[12]|SP[123]|TB(1[0-9]?|20?|[3-9]))?
@(@|TH[12]|AL[12]|SP[123]|TB(1[0-9]?|20?|[3-9])|OH(1[0-9]?|2[0-9]?|30?|[4-9]))?
(([ECMP]|HA|AK)[SD]|HS)T
[A-CV]{2}
A[cglmrstu]|B[aehikr]?|C[adeflmorsu]?|D[bsy]|E[rsu]|F[emr]?|G[ade]|H[efgos]?|I[nr]?|Kr?|L[airu]|M[dgnot]|N[abdeiop]?|Os?|P[abdmortu]?|R[abefghnu]|S[bcegimnr]?|T[abcehilm]|Uu[bhopqst]|U|V|W|Xe|Yb?|Z[nr]
(a|b)|(x|y)
(a|b) (x|y)
Ответ 4
Так как тривиально можно написать регулярное выражение, которое не содержит возможных строк, и я считаю, что также можно написать регулярное выражение, для которого вычисление соответствующей строки требует исчерпывающего поиска возможных строк всех длин, Вероятно, вам потребуется верхняя граница при запросе ответа.
Ответ 5
Самый простой способ реализовать, но определенно, самый интенсивный процессорный подход будет состоять в простом переборке.
Настройте таблицу символов с символами, которые должна содержать ваша строка, а затем просто последовательно создавайте строки и выполняйте на них команду Regex.IsMatch.
Ответ 6
Я лично считаю, что это святой Грааль рег-экс. Если бы вы могли реализовать это - даже только 3/4 работы - я не сомневаюсь, что вы будете богаты примерно через 5 минут.
Все шутя в сторону, я не уверен, что то, что вы действительно собираетесь, возможно. Reg-Ex - это очень открытый, гибкий язык и дает компьютеру достаточный объем ввода, чтобы действительно и точно находить то, что вам нужно, вероятно, невозможно.
Если я ошибаюсь, я желаю этого разработчика.
Чтобы посмотреть на это с другой точки зрения, это почти (не совсем), как предоставление компьютера, который он выводит, и имея на нем - на основе этого - напишите программу для вас. Это немного за бортом, но это как-то иллюстрирует мою мысль.