Я пишу утилиту Java, которая помогает мне генерировать множество данных для тестирования производительности. Было бы здорово указать В самом деле регулярное выражение для строк, чтобы мой генератор выдавал то, что соответствует этому. Есть ли что-то уже запеченное, что я могу использовать для этого? Или есть библиотека, которая помогает мне больше всего?
Спасибо
Другой альтернативой может быть это




Вам придется написать свой собственный парсер, как это сделал автор String :: Random (Perl). Фактически, он нигде в этом модуле не использует регулярные выражения, это просто то, к чему привыкли perl-кодеры.
С другой стороны, возможно, вы можете взглянуть на источник, чтобы получить некоторые указатели.
Обновлено: Черт, Блэр опередила меня на 15 секунд.
Редактировать:
Полный список предлагаемых библиотек по этому вопросу:
* - Зависит от dk.brics.automaton
Редактировать: Как упоминалось в комментариях, в Google Code есть библиотека для этого: https://code.google.com/archive/p/xeger/
См. Также https://github.com/mifmif/Generex, предложенный Мифмиф
Исходное сообщение:
Во-первых, я считаю, что с достаточно сложным регулярным выражением это может быть невозможно. Но вы должны уметь собрать что-нибудь для простых регулярных выражений.
Если вы посмотрите на исходный код класса java.util.regex.Pattern, вы увидите, что он использует внутреннее представление экземпляров Node. Каждый из различных компонентов шаблона имеет собственную реализацию подкласса Node. Эти узлы организованы в виде дерева.
Создавая посетителя, который проходит по этому дереву, вы должны иметь возможность вызывать метод перегруженного генератора или какой-то конструктор, который что-то собирает вместе.
Я не уверен, что Xeger настолько хорош. Он не может обрабатывать классы символов. Он не может распознать простой [\w]. Об этом говорит последняя строка их вики.
Также обратите внимание, что они зависят от dk.brics.automaton, поэтому будьте готовы добавить сторонние зависимости pom. Большинство людей не возражают против этого, но я бы хотел, чтобы было что-то более компактное.
Есть альтернатива xeger и generex. Он лишен всех этих недостатков и не устарел. Прокрутите вниз до моего ответа.
«Во-первых, я считаю, что с достаточно сложным регулярным выражением это может быть невозможно». - это не совсем верно: любое регулярное выражение, которое проходит через что нибудь, также может генерировать допустимый ввод. Объяснение: регулярные выражения относятся к типу 3 в иерархии Хомского, что означает, что они могут быть выражены как конечные автоматы. При пошаговом прохождении конечного автомата каждое ребро интерпретируется как правило для следующего символа, поэтому конечный автомат можно использовать для последовательностей разбирать или генерировать. Если у конечного автомата есть путь к терминалу, можно определить допустимую последовательность. Таким образом, это «невозможно», только если нет пути к терминалу (что было бы бесполезным регулярным выражением).
В подкасте stackoverflow 11:
Spolsky: Yep. There's a new product also, if you don't want to use the Team System there our friends at Redgate have a product called SQL Data Generator [http://www.red-gate.com/products/sql_data_generator/index.htm]. It's 5, and it just generates some realistic test data. And it does things like actually generate real cities in the city column that actually exist, and then when it generates those it'll get the state right, instead of getting the state wrong, or putting states into German cities and stuff like... you know, it generates pretty realistic looking data. I'm not really sure what all the features are.
Вероятно, это не то, что вы ищете, но это может быть хорошей отправной точкой, вместо того, чтобы создавать свою собственную.
Кажется, я ничего не могу найти в Google, поэтому я предлагаю решить эту проблему путем разбора данного регулярного выражения на мельчайшие единицы работы (\ w, [xx], \ d и т. д.) И написания некоторых основных методов для поддержки эти фразы регулярного выражения.
Итак, для \ w у вас будет метод getRandomLetter (), который возвращает любую случайную букву, и у вас также будет getRandomLetter (char startLetter, char endLetter), который дает вам случайную букву между двумя значениями.
Я знаю, что есть уже принятый ответ, но я использовал Генератор данных RedGate (тот, который упоминается в ответе Крейга), и он ДЕЙСТВИТЕЛЬНО работает для всего, что я ему бросил. Это быстро, и мне хочется использовать одно и то же регулярное выражение для генерации реальных данных для таких вещей, как регистрационные коды, которые эта штука выплевывает.
Требуется регулярное выражение вроде:
[A-Z0-9]{3,3}-[A-Z0-9]{3,3}
и генерирует множество уникальных кодов, таких как:
LLK-32U
Это какой-то большой секретный алгоритм, который разработал RedGate, и нам всем не повезло, или это то, что мы, простые смертные, действительно могли сделать?
Он далек от поддержки полного регулярного выражения PCRE, но я написал следующий метод Ruby, чтобы взять строку, подобную регулярному выражению, и создать ее вариант. (Для CAPTCHA на основе языка.)
# q = "(How (much|many)|What) is (the (value|result) of)? :num1 :op :num2?"
# values = { :num1=>42, :op=>"plus", :num2=>17 }
# 4.times{ puts q.variation( values ) }
# => What is 42 plus 17?
# => How many is the result of 42 plus 17?
# => What is the result of 42 plus 17?
# => How much is the value of 42 plus 17?
class String
def variation( values = {} )
out = self.dup
while out.gsub!( /\(([^())?]+)\)(\?)?/ ){
( && ( rand > 0.5 ) ) ? '' : .split( '|' ).random
}; end
out.gsub!( /:(#{values.keys.join('|')})\b/ ){ values[.intern] }
out.gsub!( /\s{2,}/, ' ' )
out
end
end
class Array
def random
self[ rand( self.length ) ]
end
endЯ пошел в корень, развернув мою библиотеку собственный для этого (в C#, но должно быть легко понять для разработчика Java).
Rxrdg начался как решение проблемы создания тестовых данных для реального проекта. Основная идея состоит в том, чтобы использовать существующие шаблоны проверки (регулярное выражение) для создания случайных данных, которые соответствуют таким шаблонам. Таким образом создаются действительные случайные данные.
Написать парсер для простых шаблонов регулярных выражений не так уж и сложно. Использование абстрактного синтаксического дерева для генерации строк должно быть еще проще.
ссылка больше не указывает на репозиторий. Я бы пошел с openhub.net/p/rxrdg. Однако решение не построить?
Xeger (Java) тоже может это делать:
String regex = "[ab]{4,6}c";
Xeger generator = new Xeger(regex);
String result = generator.generate();
assert result.matches(regex);
Ксегер прекрасно работает. НО убедитесь, что у вас есть автоматная банка на пути к классу или в вашем pom / gradle
Я в полете и только что увидел вопрос: я написал самое простое, но неэффективное и неполное решение. Надеюсь, это поможет вам начать писать собственный парсер:
public static void main(String[] args) {
String line = "[A-Z0-9]{16}";
String[] tokens = line.split(line);
char[] pattern = new char[100];
int i = 0;
int len = tokens.length;
String sep1 = "[{";
StringTokenizer st = new StringTokenizer(line, sep1);
while (st.hasMoreTokens()) {
String token = st.nextToken();
System.out.println(token);
if (token.contains("]")) {
char[] endStr = null;
if (!token.endsWith("]")) {
String[] subTokens = token.split("]");
token = subTokens[0];
if (!subTokens[1].equalsIgnoreCase("*")) {
endStr = subTokens[1].toCharArray();
}
}
if (token.startsWith("^")) {
String subStr = token.substring(1, token.length() - 1);
char[] subChar = subStr.toCharArray();
Set set = new HashSet<Character>();
for (int p = 0; p < subChar.length; p++) {
set.add(subChar[p]);
}
int asci = 1;
while (true) {
char newChar = (char) (subChar[0] + (asci++));
if (!set.contains(newChar)) {
pattern[i++] = newChar;
break;
}
}
if (endStr != null) {
for (int r = 0; r < endStr.length; r++) {
pattern[i++] = endStr[r];
}
}
} else {
pattern[i++] = token.charAt(0);
}
} else if (token.contains("}")) {
char[] endStr = null;
if (!token.endsWith("}")) {
String[] subTokens = token.split("}");
token = subTokens[0];
if (!subTokens[1].equalsIgnoreCase("*")) {
endStr = subTokens[1].toCharArray();
}
}
int length = Integer.parseInt((new StringTokenizer(token, (",}"))).nextToken());
char element = pattern[i - 1];
for (int j = 0; j < length - 1; j++) {
pattern[i++] = element;
}
if (endStr != null) {
for (int r = 0; r < endStr.length; r++) {
pattern[i++] = endStr[r];
}
}
} else {
char[] temp = token.toCharArray();
for (int q = 0; q < temp.length; q++) {
pattern[i++] = temp[q];
}
}
}
String result = "";
for (int j = 0; j < i; j++) {
result += pattern[j];
}
System.out.print(result);
}
Вы можете указать, какие строки используются в качестве входных данных шаблона. Во-первых, не так-то просто определить такие вещи из исходного кода. Во-вторых, если в исходном коде есть какие-либо ошибки или неточности, невозможно узнать, преднамеренные они или нет.
StringTokenizer - это устаревший класс, который сохранен по соображениям совместимости, хотя его использование в новом коде не рекомендуется. Рекомендуется, чтобы любой, кто ищет эту функциональность, использовал вместо этого метод разделения String или пакет java.util.regex.
Слишком поздно помогать оригинальному плакату, но он может помочь новичку. Generex - полезная java-библиотека, которая предоставляет множество функций для использования регулярных выражений для генерации строк (случайная генерация, генерация строки на основе ее индекса, генерация всех строк ...).
Пример :
Generex generex = new Generex("[0-3]([a-c]|[e-g]{1,2})");
// generate the second String in lexicographical order that matches the given Regex.
String secondString = generex.getMatchedString(2);
System.out.println(secondString);// it print '0b'
// Generate all String that matches the given Regex.
List<String> matchedStrs = generex.getAllMatchedStrings();
// Using Generex iterator
Iterator iterator = generex.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
// it prints 0a 0b 0c 0e 0ee 0e 0e 0f 0fe 0f 0f 0g 0ge 0g 0g 1a 1b 1c 1e
// 1ee 1e 1e 1f 1fe 1f 1f 1g 1ge 1g 1g 2a 2b 2c 2e 2ee 2e 2e 2f 2fe 2f 2f 2g
// 2ge 2g 2g 3a 3b 3c 3e 3ee 3e 3e 3f 3fe 3f 3f 3g 3ge 3g 3g 1ee
// Generate random String
String randomStr = generex.random();
System.out.println(randomStr);// a random value from the previous String list
Раскрытие
Проект, упомянутый в этом посте, принадлежит пользователю, отвечающему (Mifmif) на вопрос. Согласно правила, это необходимо поднять.
Похоже, Generex - ваш собственный проект. Не могли бы вы упомянуть в своем посте, что это ваш собственный проект по правилам здесь?
Если вы хотите сгенерировать «критические» строки, вы можете рассмотреть:
EGRET http://elarson.pythonanywhere.com/ который генерирует "злые" строки, покрывающие ваши регулярные выражения
MUTREX http://cs.unibg.it/mutrex/ который генерирует строки обнаружения ошибок путем мутации регулярного выражения
Оба являются академическими инструментами (я являюсь одним из авторов последнего) и работают достаточно хорошо.
Это очень старый вопрос, но я наткнулся на него во время собственного поиска, поэтому я добавлю пару ссылок для тех, кто может искать те же функции на других языках.
Вопрос действительно старый, хотя для меня проблема была актуальна.
Я пробовал Xeger и Generex, и, похоже, они не соответствуют моим требованиям.
Они фактически не могут обрабатывать некоторые шаблоны регулярных выражений (например, a{60000}) или для других (например, (A|B|C|D|E|F)) они просто не создают всех возможных значений. Так как другого подходящего решения я не нашел - создал свою библиотеку.
https://github.com/curious-odd-man/RgxGen
Эта библиотека может использоваться для создания как совпадающих, так и несовпадающих строк.
Также есть артефакт на центральном сервере maven.
Пример использования:
RgxGen rgxGen = new RgxGen(aRegex); // Create generator
String s = rgxGen.generate(); // Generate new random value
Я попробовал RxGen, и он работал намного лучше, чем Xeger и Generex
Вот полезный библиотека Java, который предоставляет множество функций для использования регулярного выражения для генерации String (случайная генерация, генерация String на основе его индекса, генерация всей String ..), проверьте здесь