Regulären Ausdruck umkehren?

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.
Antworten
Benutzeravatar
_johannes
User
Beiträge: 20
Registriert: Montag 19. Juni 2006, 17:37

Ich möchte folgendes machen:

In einer Datei gibt es Zeilen mit folgenden Mustern
1 irgendwas/[irgendwas]/irgendwas/irgendwas/[irgendwas]/irgendwas
2 irgendwas/[irgendwas][irgendwas]/irgendwas/irgendwas/[irgendwas][irgendwas]/irgendwas
3 irgendwas/[irgendwas][irgendwas][irgendwas]/irgendwas/irgendwas/[irgendwas][irgendwas][irgendwas]/irgendwas
4 ...
Ich möchte jetzt alle Zeilen löschen, in denen mehr als einmal [irgendwas] direkt aufeinander folgt. Am Ende soll also eine Datei rauskommen, in der nur noch solche Zeilen wie hier die Zeile 1 übrigbleiben.

Hier mein Versuch:

Code: Alles auswählen

filein = file('/pfad/datei.txt')

for line in filein.readlines():
	treffer1 = re.search(r'(\[.+\]){2}', line)
       if treffer1 != None:
           print treffer1
Damit habe ich alle Zeilen, die ich eigentlich rauswerfen will. Aber eigentlich wäre es doch cleverer, nur die Zeilen rauszusuchen, die ich behalten will und die dann in eine neue Datei zu speichern.
Daher: Wie kann ich die Regex einfach umkehren? Mit sowas wie "not" oder so?
Bin, wie Ihr sicher gemerkt habt, noch ziemlicher Newbie und was das Programmieren angeht Autodidakt, deshalb bitte ich um Nachsicht, wenn mir einige Selbstverständlichkeiten nicht geläufig sind.

Grüße, _johannes
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Wald und Bäume? :wink:

Code: Alles auswählen

if treffer1 == None:
  print line
oder gleich

Code: Alles auswählen

if not re.search(r'(\[.+\]){2}', line):
  print line
Benutzeravatar
_johannes
User
Beiträge: 20
Registriert: Montag 19. Juni 2006, 17:37

:shock: :D
Aua, ich bin gegen einen Baum gelaufen.
Danke.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hallo Johannes,

mein Vorschlag wäre auch das Ausschließen:

Code: Alles auswählen

import re
lSauber = []

for sLine in filein.readlines():
    if re.search(r'(\[.+?\]){2}', sLine):
        lSauber.append(sLine)

print lSauber
Ob Du nun eine neue Liste mit den übrigen Strings anlegst oder nach der Schleife die ungültigen Teile löschst, bleibt Dir überlassen.

Falls Du Deinen re-Ausdruck zum Filtern verwenden möchtest, solltest Du darauf achten, dass ".+" so viele Zeichen nimmt, wie es bekommen kann.
Das heißt, es ist gültig für "[irgendwas]/irgendwas/[irgendwas]" genauso wie für "[irgendwas][irgendwas]"... und ruckzuck fehlt Dir /irgendwas/. :)

Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
_johannes
User
Beiträge: 20
Registriert: Montag 19. Juni 2006, 17:37

Stimmt, das mit der Gierigkeit habe ich auch gelesen.
Aber bei mir kommt komischerweise trotzdem das korrekte Ergebnis raus:
1\Farn\4\'f&rn\[farn]\'f&rn\[farn]\[CVCC]\[CVCC]\farn\farn
2\Farnkraut\3\'f&rn-krBt\[farn][kraut]\'f&rn-krBt\[farn][kraut]\[CVCC][CCVVC]\[CVCC][CCVVC]\farn#kraut\farn#kraut
Wenn ich darauf

Code: Alles auswählen

for line in filein.readlines():
	if not re.search(r'(\[.+\]){2}', line):
		print line
anwende, bekomme ich trotzdem nur die erste Zeile als Ergebnis.
Also doch keine Gierigkeit?
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hi Johnannes,

ja, wenn Du nur prüfen willst, ob das Muster in der Zeile vorkommt, dann geht das.

Schwierig wird es erst, wenn Du z.B. alle Vorkommen mit re.sub durch einen anderen String ersetzen möchtest.

Die direkte Gegenüberstellung zeigt ganz gut, was ich meine:

Code: Alles auswählen

s = """2\Farnkraut\3\'f&rn-krBt\[farn][kraut]\'f&rn-krBt\[farn][kraut]\[CVCC][CCVVC]\[CVCC][CCVVC]\farn#kraut\farn#kraut"""
import re
print "gierig:      ", re.search(r'(\[.+\]){2}', s).group()
print "nicht gierig:", re.search(r'(\[.+?\]){2}', s).group()
ergibt:
gierig: [farn][kraut]'f&rn-krBt\[farn][kraut]\[CVCC][CCVVC]\[CVCC][CCVVC]
nicht gierig: [farn][kraut]
Ohne ? bedeutet das Muster wörtlich: "Liefere den String vom ersten '[' bis zum letzten ']', auf das noch ein '[' folgt, verknüpft mit dem String vom letzten '[' bis zum letzten ']'." Kurz gesagt: Du bekommst alles vom ersten '[' bis zum letzten ']' Zeichen, wenn dazwischen der Teil '][' vorkommt.
Bei der nicht gierigen Form wird der String vom '[' bis zum folgenden ']' zurückgegeben, wenn mindestens ein Zeichen dazwischen steht (kein line feed). Ebenfalls zweimal hintereinander.

(EDIT: Backslashes eingefügt)
Vereinfacht gesehen hätte das Muster r'\]\[' also völlig ausgereicht, um die Ausschlussbedingung zu formulieren. :-)

Grüße,
der Michel
Zuletzt geändert von Michael Schneider am Sonntag 13. August 2006, 19:44, insgesamt 1-mal geändert.
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
_johannes
User
Beiträge: 20
Registriert: Montag 19. Juni 2006, 17:37

Ah, jetzt hab ich's kapiert.
Das kann ich bestimmt noch gut gebrauchen, danke.
Antworten