Подобный регулярному выражению синтаксис или CFG для генерации декартового произведения конкатенированных строковых переменных и литералов - PullRequest
0 голосов
/ 19 июня 2009

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

myprogram.{version1|version2} -arg1 {1|2|4} {-arg2|}

или:

myprogram.{0} -arg1 {1} {2}
0: "version1" "version2"
1: "1" "2" "4"
2: "-arg2" ""

и будет выдавать:

myprogram.version1 -arg1 1 -arg2
myprogram.version1 -arg1 1
myprogram.version1 -arg1 2 -arg2
myprogram.version1 -arg1 2
myprogram.version1 -arg1 4 -arg2
myprogram.version1 -arg1 4
myprogram.version2 -arg1 1 -arg2
myprogram.version2 -arg1 1
myprogram.version2 -arg1 2 -arg2
myprogram.version2 -arg1 2
myprogram.version2 -arg1 4 -arg2
myprogram.version2 -arg1 4

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

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

Самое главное, это решение не должно требовать от меня написаниялюбой дополнительный код синтаксического анализа, если я хочу добавить дополнительные параметры аргумента к «перекрестному произведению» строк, которые я генерирую.У меня уже есть Perl-скрипт, который делает это с набором вложенных циклов for для каждой «переменной», которые должны меняться каждый раз, когда я меняю число или характер переменных.

Ответы [ 2 ]

3 голосов
/ 19 июня 2009

Пока фигурные скобки не вложены, регулярные выражения будут работать нормально. Если вам требуется вложение, вы можете добавить дополнительную рекурсию в язык реализации.

Вот пример на Python:

import re

def make_choices(template):
    pat = re.compile(r'(.*?)\{([^{}]+)\}',re.S)

    # tokenize the string
    last_end = 0
    choices = []
    for match in pat.finditer(template):
        prefix, alts = match.groups()
        if prefix:
            choices.append((prefix,)) # as a tuple
        choices.append(alts.split("|"))
        last_end = match.end()

    suffix = template[last_end:]
    if suffix:
        choices.append((suffix,))

    # recursive inner function
    def chooser(index):
        if index >= len(choices):
            yield []
        else:
            for alt in choices[index]:
                for result in chooser(index+1):
                    result.insert(0,alt)
                    yield result

    for result in chooser(0):
        yield ''.join(result)

Пример:

>>> for result in make_choices('myprogram.{version1|version2} -arg1 {1|2|4} {-arg2|}'):
...     print result
...
myprogram.version1 -arg1 1 -arg2
myprogram.version1 -arg1 1
myprogram.version1 -arg1 2 -arg2
myprogram.version1 -arg1 2
myprogram.version1 -arg1 4 -arg2
myprogram.version1 -arg1 4
myprogram.version2 -arg1 1 -arg2
myprogram.version2 -arg1 1
myprogram.version2 -arg1 2 -arg2
myprogram.version2 -arg1 2
myprogram.version2 -arg1 4 -arg2
myprogram.version2 -arg1 4

Вы можете использовать os.system() для выполнения команд из Python:

#!/etc/env python
import sys, os

template = ' '.join(sys.args)
failed = 0
total = 0
for command in make_choices(template):
    print command
    if os.system(command):
        print 'FAILED'
        failed += 1
    else:
        print 'OK'
    total += 1

print
print '%d of %d failed.' % (failed,total)

sys.exit(failed > 0)

А затем в командной строке:

user:/home/> template.py 'program.{version1|version2}'
program.version1
OK
program.version2
FAILED

1 of 2 failed.
2 голосов
/ 19 июня 2009

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

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

...