代码之家  ›  专栏  ›  技术社区  ›  Matt J Jørgen Fogh

用于生成连接字符串变量和文本的笛卡尔积的类regex语法或cfg

  •  0
  • Matt J Jørgen Fogh  · 技术社区  · 15 年前

    我正在编写一个模拟器,并希望通过使用不同的命令行参数集调用模拟器的许多实例来运行研究。我读过 this 问题和其他一些问题,它们看起来很接近,但实际上我不是在寻找满足特定regex的随机数据,我希望 全部的 与regex匹配的字符串。示例输入文件如下所示:

    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
    

    我可以想象这样的东西已经存在,我只是不知道要搜索的正确术语。任何帮助都将不胜感激。如果需要的话,我可以自己实现一个抽象技术或算法,但是如果它是一个预先存在的工具,我希望它是免费的(至少在beer中是这样),并在Linux上运行。

    我知道我可能会遗漏一些细节,如果必要的话,我可以更具体地描述一些适当的事情,而不是在前面用大量细节淹没人们。这完全可能是我走错了路,我欢迎所有的解决方案,即使它们以不同的方式解决我的问题。

    最重要的是,如果我想为我生成的字符串的“交叉积”添加更多参数选项,这个解决方案不应该要求我编写任何额外的解析代码。我已经有了一个Perl脚本,它用一组嵌套的 for 循环每个“变量”,每次我更改变量的数量或性质时,这些变量都必须更改。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Markus Jarderot    15 年前

    只要大括号没有嵌套,正则表达式就可以正常工作。如果需要嵌套,可以在实现语言中添加一些额外的递归。

    下面是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
  •  2
  •   Lee    15 年前

    你不是真的在寻找正则表达式是为之设计的。您只是在寻找一个工具,它可以生成离散选项的组合。

    根据所有可能的参数集,实际上可能不需要详尽的组合列表。不管怎样,你应该调查一下 Pairwise Testing . 我知道一个事实 PICT tool 可以生成您想要的测试用例的详尽列表或成对列表。