2009-06-18 9 views
0

Ich schreibe einen Simulator und würde gerne Studien durchführen, indem ich viele Instanzen des Simulators mit verschiedenen Befehlszeilenargumenten aufrufen würde. Ich habe gelesen this Frage und mehrere andere, und sie scheinen nah, aber ich bin eigentlich nicht auf der Suche nach zufälligen Daten eine bestimmte Regex erfüllen, würde ich die alle Zeichenfolgen, die die Regex übereinstimmen. Ein Beispiel Eingabedatei würde wie folgt aussehen:Regex-ähnliche Syntax oder CFG zum Generieren eines kartesischen Produkts von verketteten String-Variablen und Literalen

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

oder:

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

und produzieren würde:

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 

ich so etwas wie dies könnte mir vorstellen, bereits existiert, ich habe gerade don‘ Ich kenne den richtigen Suchbegriff. Jede Hilfe würde sehr geschätzt werden. Ich kann eine abstrakte Technik oder einen Algorithmus selbst implementieren, wenn es sein muss, aber wenn es ein bereits existierendes Werkzeug ist, würde ich es vorziehen, dass es frei ist (zumindest wie in Bier) und unter Linux läuft.

Ich weiß, dass ich wahrscheinlich einige Details verlasse und bei Bedarf genauer auf die entsprechenden Dinge eingehen kann, anstatt Leute mit vielen Details im Voraus zu überschwemmen. Es ist durchaus möglich, dass ich dies falsch mache, und ich bin zu allen Lösungen willkommen, auch wenn sie mein Problem auf andere Weise lösen.

Am wichtigsten, diese Lösung sollte nicht erfordern, dass ich zusätzlichen Parsing-Code schreibe, wenn ich dem "Cross-Produkt" von Strings, die ich generiere, weitere Argumentoptionen hinzufügen möchte. Ich habe bereits ein Perl-Skript, das dies mit einer Reihe von verschachtelten for Schleifen über jede "Variable" macht, die jedes Mal geändert werden muss, wenn ich die Anzahl oder Art der Variablen ändere.

Antwort

3

Solange die geschweiften Klammern nicht verschachtelt sind, funktionieren reguläre Ausdrücke gut. Wenn Sie eine Verschachtelung benötigen, können Sie zusätzliche Rekursion in der Implementierungssprache hinzufügen. Hier

ist ein Beispiel in 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) 

Beispiel:

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

Sie os.system() verwenden könnten die Befehle aus Python ausführen:

#!/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) 

Und dann auf die Befehlszeile:

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

1 of 2 failed. 
+0

Vielen Dank!Das funktioniert gut für meinen aktuellen Anwendungsfall, und wenn es an der Zeit ist, Rekursion zur Syntax hinzuzufügen, höre ich auf, Python zu lernen und benutze es als meine "Hallo Welt" (es sei denn, Sie sind gelangweilt;) –

2

Sie suchen nicht wirklich nach etwas, für das reguläre Ausdrücke entworfen wurden. Sie suchen nur nach einem Werkzeug, das Kombinationen von diskreten Optionen generiert.

Abhängig von der Menge aller möglichen Argumente ist eine erschöpfende Liste von Kombinationen möglicherweise nicht notwendig. Unabhängig davon sollten Sie in Pairwise Testing suchen. Ich weiß für eine Tatsache, dass die PICT tool Sie entweder die erschöpfende Liste oder die paarweise Liste von Testfällen generieren können, die Sie wünschen.

+0

Einverstanden; Die Funktionalität, nach der ich suche, ist ganz anders als die Implementierung von Regexen in jeder mir bekannten Sprache; Wie ich versucht habe, im Titel zu vermitteln, ist die gefällige Syntax für die Kombination von Literalen und Variablen das, wonach ich suche. Was Ihren zweiten Punkt betrifft, war meine Idee, dass ich eine separate Eingabedatei für jede Reihe von Jobs schreiben würde, die ich gerne machen würde, so dass die vollständige Liste tatsächlich das ist, was ich möchte. Wenn es ein Schema gibt, das es mir erlaubt, den Raum möglicher Argumente für mein Programm anzugeben und einfach nur eine Teilmenge davon in jeder Eingabedatei auszuwählen, ist das auch in Ordnung. –

+0

Es klingt wie das PICT-Tool wird in der Lage sein, mit dem zu tun, was Sie wollen. Sie geben den Raum mit möglichen Argumenten an und können dann die erschöpfende Liste oder die paarweise, ternäre oder andere N-Reihenfolge kurz vor der Vollständigkeit erzeugen. Aber, abhängig von der Größe Ihres Problembereichs ... möchten Sie vielleicht die Forschung auf der Website betrachten, erschöpfend ist möglicherweise nicht notwendig. Natürlich, wenn Sie weniger als hundert Testfälle sprechen, dann wen interessiert es, wenn es nicht notwendig ist. – Lee

+0

Ja, PICT sieht aus, als ob es tun würde, was ich will, obwohl es für meine Zwecke ein wenig übertrieben ist. Dies ist für das Ausführen einer sorgfältig ausgewählten Reihe von gerichteten Simulationen, nicht für das Testen, so dass ich wirklich nur eine Kurzschrift für das Generieren von vielen Strings mit gemeinsamer Struktur benötigt; Sie können Ihre Eingaben immer so schreiben, dass das kartesische Produkt genau die Menge von Dingen ist, die Sie wollten (obwohl es sich verschlingen könnte, dies zu tun, wenn Sie ein nichtlineares, mangels eines besseren Begriffs erkunden, Stück des Parameterraums). –