3 Stimmen

Parametrischer regulärer Ausdruck in Python

Gibt es in Python einen besseren Weg, um Zeichenketten in reguläre Ausdrücke parametrisieren als es manuell so zu machen:

test = 'flobalob'
names = ['a', 'b', 'c']
for name in names:
    regexp = "%s" % (name)
    print regexp, re.search(regexp, test)

Dieses Beispiel von noddy versucht, jeden Namen der Reihe nach zu finden. Ich weiß, dass es dafür bessere Möglichkeiten gibt, aber es ist ein einfaches Beispiel, um den Punkt zu illustrieren.


Die Antwort scheint zu lauten: Nein, es gibt keine echte Alternative. Der beste Weg, reguläre Ausdrücke in Python zu parametrisieren, ist wie oben beschrieben oder mit Ableitungen wie str.format() . Ich habe versucht, eine allgemeine Frage zu schreiben, anstatt fix ma codez, kthxbye". . Für diejenigen, die es noch interessiert, habe ich hier ein Beispiel ausgearbeitet, das meinen Bedürfnissen näher kommt:

for diskfilename in os.listdir(''):
    filenames = ['bob.txt', 'fred.txt', 'paul.txt']
    for filename in filenames:
        name, ext = filename.split('.')
        regexp = "%s.*\.%s" % (name, ext)
        m = re.search(regexp, diskfilename)
        if m:
          print diskfilename, regexp, re.search(regexp, diskfilename)
          # ...

Ich versuche, den "Typ" einer Datei anhand ihres Dateinamens herauszufinden, und zwar in der Form <filename>_<date>.<extension> . In meinem echten Code ist die filenames Array ist ein dict, das eine Funktion enthält, die aufgerufen wird, sobald eine Übereinstimmung gefunden wurde.

Andere Möglichkeiten, die ich in Betracht gezogen habe:

  • Einen regulären Ausdruck im Array haben. Ich habe bereits ein Array von Dateinamen ohne reguläre Ausdrücke Magie, so dass ich abgeneigt bin, dies zu tun. Ich habe dies an anderer Stelle in meinem Code getan und seine ein Chaos (obwohl notwendig dort).

  • Übereinstimmung nur am Anfang des Dateinamens. Dies würde zwar funktionieren, aber mit .bak-Kopien von Dateien usw. nicht funktionieren. Irgendwann werde ich wahrscheinlich das Datum aus dem Dateinamen extrahieren wollen, also müsste ich sowieso einen regulären Ausdruck verwenden.


Danke für die Antworten, die Alternativen zu regulären Ausdrücken vorschlagen, um das gleiche Ergebnis zu erzielen. Ich war mehr daran interessiert, reguläre Ausdrücke für jetzt und für die Zukunft zu parametrisieren. Ich bin nie auf fnmatch Es ist also auf lange Sicht sehr nützlich.

6voto

paprika Punkte 2333

Nun, da Sie eine Regexp aus einer Zeichenkette erstellen, sehe ich keine andere Möglichkeit. Aber Sie könnten die Zeichenkette selbst parametrisieren mit einem Wörterbuch:

d = {'bar': 'a', 'foo': 'b'}
regexp = '%(foo)s|%(bar)s' % d

Oder, je nach Problemstellung, können Sie auch Listenauflösungen verwenden:

vlist = ['a', 'b', 'c']
regexp = '|'.join([s for s in vlist])

EDITAR: Mat hat seine Frage geklärt, das macht die Dinge anders und das oben Gesagte ist völlig irrelevant.

Ich würde wahrscheinlich einen Ansatz wie diesen wählen:

filename = 'bob_20090216.txt'

regexps = {'bob': 'bob_[0-9]+.txt',
           'fred': 'fred_[0-9]+.txt',
           'paul': 'paul_[0-9]+.txt'}

for filetype, regexp in regexps.items():
    m = re.match(regexp, filename)
    if m != None:
        print '%s is of type %s' % (filename, filetype)

2voto

jfs Punkte 370717
import fnmatch, os

filenames = ['bob.txt', 'fred.txt', 'paul.txt']

                  # 'b.txt.b' -> 'b.txt*.b'
filepatterns = ((f, '*'.join(os.path.splitext(f))) for f in filenames) 
diskfilenames = filter(os.path.isfile, os.listdir(''))
pattern2filenames = dict((fn, fnmatch.filter(diskfilenames, pat))
                         for fn, pat in filepatterns)

print pattern2filenames

Ausgabe:

{'bob.txt': ['bob20090217.txt'], 'paul.txt': [], 'fred.txt': []}

Es folgen Antworten auf frühere Überarbeitungen Ihrer Frage:


Ich verstehe Ihre aktualisierte Frage nicht, aber filename.startswith(prefix) könnte in Ihrem speziellen Fall ausreichend sein.

Nachdem Sie Ihre Frage aktualisiert haben, ist die alte Antwort unten weniger relevant.


  1. Verwenden Sie re.escape(name) wenn Sie eine Übereinstimmung mit einem name buchstäblich.

  2. Jedes Tool, das für die Parametrisierung von Zeichenketten zur Verfügung steht, ist hier anwendbar. Zum Beispiel:

    import string
    print string.Template("$a $b").substitute(a=1, b="B")
    # 1 B

    Oder mit str.format() in Python 2.6+:

    print "{0.imag}".format(1j+2)
    # 1.0

2voto

SilentGhost Punkte 285785

Können sein Globus y fnmatch Module für Sie hilfreich sein können?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X