Создайте программу, которая вводит регулярное выражение и выводит строки, удовлетворяющие этому регулярному выражению

Я думаю, что название точно резюмирует мой вопрос, но просто немного уточнить.

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

Примечание: функция не должна генерировать строка, удовлетворяющая регулярному выражению (причина, которая была бы бесконечным числом строка для многих регулярных выражений). Достаточно только выборки из множества допустимых строк.

насколько это возможно? Если решение слишком сложное/большое, я доволен общей дискуссией / планом. Кроме того, меня интересуют любые существующие программы или библиотеки (.NET), которые это делают.

6 ответов


ну регулярное выражение конвертируется в DFA, который можно рассматривать как график. Чтобы создать строку, заданную этим DFA-графом, вы просто найдете путь от начального состояния до конечного состояния. Вам просто нужно подумать о том, как вы хотите обрабатывать циклы (возможно, пересечь каждый цикл хотя бы один раз, чтобы получить выборку? n раз?), но я не понимаю, почему это не сработает.


этой утилита на UtilityMill будет инвертировать некоторые простые regexen. Он основан на этот пример из pyparsing wiki. Тестовые примеры для этой программы:

[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)

Это можно сделать с помощью обход DFA (включает псевдокод) или иначе, пройдя дерево абстрактного синтаксиса regex напрямую или сначала преобразуясь в NFA, как объясняется Дуг Макилрой: статьи и Хаскел код. (Он считает, что подход NFA идет быстрее, но он не сравнивал его с DFA.)

все они работают с регулярными выражениями без обратных ссылок - то есть "реальные" регулярные выражения, а не Perl регулярное выражение. Для обработки дополнительных функций Perl было бы проще всего добавить постфильтр.

добавлено: код для этого в Python, Питер Норвиг и я.


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


самый простой способ реализовать, но, безусловно, наиболее интенсивный подход к процессору-это просто грубая сила. Настройте таблицу символов с символами, которые должна содержать строка, а затем последовательно генерируйте строки и выполняйте регулярное выражение.Выполняется на них.


Я лично считаю, что это Святой Грааль reg-ex. Если бы вы могли реализовать это - даже только 3/4 работы - я не сомневаюсь, что вы были бы богаты примерно через 5 минут.

все шутки в сторону, я не уверен, что то, что вам действительно идет после возможно. Reg-Ex-очень открытый, гибкий язык, и дать компьютеру достаточно примеров ввода, чтобы действительно и точно найти то, что вам нужно, вероятно, не представляется возможным.

Если я неправ, я хочу, спасибо, что разработчик.

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