Reguläre Ausdrücke

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

Hi Leute,

ich habe ein kleines Problem mit einem regulären Ausdruck, ich möchte folgende Strings substituieren:

"FId_*" zu "FId_unused" und

FESTWERT DFES_Cls.*Wert 1.0 zu FESTWERT DFES_Cls.*Wert 2.0

Das heißt ich will alle ändern, beim ersten Ausdruck machen die Anführungszeichen Probleme, ja die sind in der TEXT-Datei drin, und auch ein wichtiges Kriterium, beim zweiten Ausdruck klappt es auch nicht...was mache ich nur falsch?

Code: Alles auswählen

import re
from sys import *

# -------------------------------------------------------------------------------------
# --- Name     : readFromTextData
# --- Funktion : Liest eine Datei ein und gibt die Zeilen als Liste zurueck
# --- Parameter: path : Pfad der Datei
# --- Rueckgabe :Zeilen als Liste
# -------------------------------------------------------------------------------------
def readFromTextData( path ):
    fid = open(path, 'r')
    #lines_ = fid.readlines()
    lines_ = fid.read()
    fid.close()
    return lines_


# Hauptprogramm das den Parameter (den Pfad zur DCM ) entgegennimmt
if  __name__ == '__main__':
#print len(argv)
    if len(argv) == 1:
	print "usage: ersetzung DCM_FIle" 
    else:
        worktxt = re.sub('\"FId_*\"', '\"FId_UNUSED\"', readFromTextData(argv[1]))
        #print worktxt
#        print (re.search("FId_*",readFromTextData(argv[1]))).group()
        worktxt = re.sub("FESTWERT DFES_Cls*WERT 1.0","FESTWERT DFES_Cls*WERT 2.0", worktxt)
	outF = open("ersetzt.DCM", "w")
        outF.write(worktxt)
        outF.close()

Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und wozu brauchst du da reguläre Ausdrücke? Ein simples String-Replace tut es in diesem Fall doch auch.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

funktionieren denn da die metazeichen auch?
Die * sind ja sehr relevant da ich nicht immer weiß wieviele Zeichen dazwischen liegen
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

xpaffx hat geschrieben:funktionieren denn da die metazeichen auch?
Nein, tun sie nicht.
Aber so wie du sie im Beispielcode verwendest match du eine beliebige Anzahl von Unterstrichen (`FId_*`) und eine beliebige Anzahl von s (`FESTWERT DFES_Cls*WERT 1.0`). Insbesondere beim letzten sagst du erst dass du `FESTWERT DFES_Cls.*Wert 1.0` ersetzen willst, aber dann`FESTWERT DFES_Cls*Wert 1.0` ersetzt...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@xpaffx: Dann beschreibe Dein Problem nochmal genauer und zwar so dass *genau* klar ist was literale Zeichen und was Platzhalter sind. Wenn Du sagst "FId_*" soll zu "FId_unused" werden, ist das Sternchen dann ein Sternchen oder ein Platzhalter für beliebige Zeichen (ausser vielleicht Leerzeichen, Ziffern, etc.)?

Wenn Du Dein Problem auf diese Weise *genau* beschreibst, löst Du das ganze vielleicht sogar selbst. Weil Du dann im Grunde einen regulären Ausdruck beschreibst, den Du haben möchtest. :-)
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

Also diese "*" stellen beliebige Zeichen dar, das können Buchstaben, Zahlen, Sonderzeichen, Zeilenumbrüche usw. einer beliebigen Länge sein.

Ich weiß eben nicht wie die FId's vorher aussehen , das selbe gilt für das zweite Beispiel...dort können ebenso beliebige zeilen davor stehen ...
BlackJack

Tja dann liegt das Problem daran das ein '*' in regulären Ausdrücken nicht für beliebige Zeichen steht, sondern den Teil der davor steht modifiziert. '*' bedeutet 0 oder mehrfache Vorkommen des Teils der vor dem '*' steht.

Dein erstes Muster muss also so aussehen '"FId_.*?"'. Das ist '"FId_' gefolgt von 0 oder mehr beliebigen Zeichen. Das '.' steht für ein beliebiges Zeichen, das '*' für das 0 oder mehr. Das '?' brauchst Du noch weil reguläre Ausdrücke normalerweise "greedy" sind und versuchen soviel wie möglich zu matchen. In den beliebigen Zeichen ('.') ist auch das " enthalten, wenn davon also mehrere in der Zeile vorkommen, wird sonst bis zum letzen gematcht.

Und wenn Du Teile aus dem Muster in der Ersetzung haben willst, dann kannst Du dort nicht einfach wieder ein Muster angeben. Die Zeichenkette für die Ersetzung wird ja nicht auf die Eingabe angewendet. Dort musst Du eine Referenz auf die Gruppe im Suchmuster angeben. Dass heisst Du musst das dort auch mit Klammern gruppieren.

Der Ausdruck sieht dann analog zum ersten Beispiel so aus 'FESTWERT DFES_Cls(.*?)WERT 1.0'. Die Klammern sorgen dafür, dass das was dort passt in einer Gruppe gespeichert wird. Die sind durchnummeriert. Das ist also die erste Gruppe und die kann man in der Ersetzungszeichenkette mit r'\1' einfügen: r'FESTWERT DFES_Cls\1WERT 2.0'

Wenn Du so etwas öfter machen musst, solltest Du mal ein gutes Tutorial zu regulären Ausdrücken durcharbeiten.
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

Danke, jetzt ist es natürlich klar wieso das ganze nicht geklappt hat.

Nur leider geht das zweite immer noch nicht obwohl ich mich an deine Anweisungen gehalten habe:

Code: Alles auswählen

        worktxt = re.sub("FESTWERT DFES_Cls(.*?)WERT 1.0", r'FESTWERT DFES_Cls\1WERT 2.0', worktxt)
BlackJack

Also damit wird bei mir 'FESTWERT DFES_ClsFooWERT 1.0' zu 'FESTWERT DFES_ClsFooWERT 2.0'.

Was passiert bei Dir? Und wie sieht denn die Eingabe genau aus? Du hast in Deinen Beschreibungen mal 'WERT' und mal 'Wert' geschrieben. Das macht natürlich einen Unterschied.
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

Also die Datei hat z.B. den Inhalt(Auszug):

FESTWERT DFES_Cls.DFC_ACCIaDesMax_C
LANGNAME "DFES / Fehlerklasse fuer Pruefung DFC_ACCIaDesMax"
FUNKTION dfes_class_auto
EINHEIT_W "-"
WERT 1.0
END

Und danach sieht sie immer noch genauso aus, das mit dem UnUsed hat jedoch geklappt
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

probleme bereiten anscheinend die zeilenumbrüche...ansonsten geht es nämlich...weiß einer wieso es nicht geht oder besser wie es geht?!
BlackJack

Der Punkt trifft normalerweise nicht auf den Zeilenwechsel zu. Dazu muss der reguläre Ausdruck mit `re.DOTALL` als Flag übersetzt werden. Das kann man bei `re.sub()` nicht machen, also müsstest Du den Ausdruck mit `re.compile()` übersetzen und von dem Objekt dann die `sub()`-Methode verwenden.
Jona
User
Beiträge: 94
Registriert: Sonntag 23. September 2007, 23:25

du könntest die datei auch zeilenweise einlesen und bearbeiten.
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

ja klar aber es muss doch so jetzt gehen ...bis auf diesen kleinen fehler mit den zeilenumbrüchen??
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

'1.0' und '2.0' müssten noch in '1\.0' und '2\.0' umgewandelt werden, sonst steht der Punkt ja wieder für ein beliebiges Zeichen.
MfG
HWK
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

Nein das hat nicht gereicht, also hier folgendes müsste doch eigentlich gehen...tut es aber nicht:

Code: Alles auswählen

        worktxt = re.sub("FESTWERT DFES_Cls(.*?)WERT 1\.0", r'FESTWERT DFES_Cls\1WERT 2\.0','FESTWERT DFES_Cls\nhi\nWERT 1.0')
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Hast du BlackJacks Rat befolgt?
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

oh die antwort wurde vorhin in meinem browser nicht dargestellt...seltsam danke ist jetzt klar teste es morgen ;)
xpaffx
User
Beiträge: 13
Registriert: Montag 3. September 2007, 19:55

danke sehr, es hat geklappt!!! python rulez ;p
mulder
User
Beiträge: 49
Registriert: Montag 15. Oktober 2007, 10:36
Wohnort: nürnberg

moin!

ich habs jetz (wiedermal) lange versucht und denke das ich einfach mal den wald vor lauter baeumen nicht seh! .. :oops:

ich moechte einen re mit einer variable "fuellen" und dann einen findall machen!

aber der pattern will mit ueberhaupt nicht gelingen!

Code: Alles auswählen

        PATTERN = re.compile(r'(NAME;.*)')
        PATTERN =  "r\'" + NAME + ";.*\'"
das sind meine beiden letzten erfolglosen versuche! .. :cry:

also NAME ist nen varianlen name. der versuch mit dem compile sieht nicht nur hilflos aus ... er ist es auch .. :oops: ne also .. ich hab da noch nicht die richtige syntax zusammen!...
" schlimmer als stress ist, keinen zu haben"
Antworten