Seite 1 von 1

Regulären Ausdruck umkehren?

Verfasst: Montag 7. August 2006, 17:15
von _johannes
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

Verfasst: Montag 7. August 2006, 21:02
von Joghurt
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

MitderHandgegendieStirnhau

Verfasst: Montag 7. August 2006, 21:49
von _johannes
:shock: :D
Aua, ich bin gegen einen Baum gelaufen.
Danke.

Verfasst: Montag 7. August 2006, 21:50
von Michael Schneider
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

Verfasst: Montag 7. August 2006, 22:05
von _johannes
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?

Verfasst: Montag 7. August 2006, 22:38
von Michael Schneider
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

Verfasst: Montag 7. August 2006, 22:44
von _johannes
Ah, jetzt hab ich's kapiert.
Das kann ich bestimmt noch gut gebrauchen, danke.