Seite 1 von 1

Zahlen in Datei ersetzen

Verfasst: Samstag 21. März 2009, 01:41
von _johannes
Hallo mal wieder,

Ich hänge mal wieder an einem Problem. Passiert mir öfter da ich Python-Autodidakt bin ;-)

Also, ich möchte ein kleines Skript schreiben, das Folgendes macht:
In einer Datei in der ganz viele Zahlenkolonnen stehen (es sind Messwerte und bestimmte Ereigniskodierungen) bestimmte Zahlen ersetzen und das Ganze wieder abspeichern.

Ein Beispiel:

Code: Alles auswählen

    8.192    130051  99
    8.936    141583 141
   10.856    171343   1
   14.896    233963 195
   15.396    241713   2
   17.400    272775  99
   18.148    284369 255
   20.068    314129  14
   24.200    378175 195
   24.488    382639   1
Es geht mir dabei um die jeweils auf die 195\n folgende Zahl in der letzten Spalte. Kommt eine 2\n, soll sie durch 77\n ersetzt werden, kommt eine 1\n, durch 70\n. Alle anderen Zahlen und Leerzeichen sollen identisch zur Ursprungsdatei bleiben.

Hier mein Skriptversuch, ich versuche erstmal nur die 2er in 77er zu verwandeln:

Code: Alles auswählen

import os
import re

file1 = file('ursprungsdatei.txt')

regexwrong = r'.+195\n.+2\n'

lines = file1.read()

a = re.search(regexwrong, lines)
 if a != None:
  print re.sub(r'\ 2\n', '77\n', a.group())	
Das macht mir die erste Ersetzung richtig. Mein Problem: Wie kann ich hier iterieren? Also alle 2\n in der Datei durch 77\n ersetzen und nicht nur den ersten Treffer? Welche Schleifenkonstruktion muss/kann ich hier nehmen? Meine bisherigen Versuche mit for oder while schlugen fehl.

Hat jemand einen Tipp für mich?

Grüße,
Johannes

Verfasst: Samstag 21. März 2009, 01:51
von Dauerbaustelle

Code: Alles auswählen

In [1]: text = """
   ...:     8.192    130051  99
   ...:     8.936    141583 141
   ...:    10.856    171343   1
   ...:    14.896    233963 195
   ...:    15.396    241713   2
   ...:    17.400    272775  99
   ...:    18.148    284369 255
   ...:    20.068    314129  14
   ...:    24.200    378175 195
   ...:    24.488    382639   1
   ...: """

In [2]: print text.replace('2\n', '77\n').replace('1\n', '70\n')
    8.192    130051  99
    8.936    141583 1470
   10.856    171343   70
   14.896    233963 195
   15.396    241713   77
   17.400    272775  99
   18.148    284369 255
   20.068    314129  14
   24.200    378175 195
   24.488    382639   70

Verfasst: Samstag 21. März 2009, 01:59
von hendrikS
Ich würde vielleicht zeilenweise Pärchen bilden und dann drüberiterieren.
Kann man mit zip machen. Z.Bsp. so:

Code: Alles auswählen

a=[99,141,1,195,2,99,255,14,195,1]
b=zip(a,a[1:])
print b
Die Zahlen in a mußt Du natürlich durch die Zeilen erstzen.

Verfasst: Samstag 21. März 2009, 12:56
von momo
Hallo !

So geht es:

Code: Alles auswählen

import os
import re

file1 = file('text.txt')
file2 = file('resultat.txt','w')
regexwrong = r'.+195\n.+2\n'

merke = 0
for line in file1.readlines():
    if merke:
        line = re.sub('2$','77',line)
        line =re.sub('1$','70',line)
        merke = 0

    else:
        if re.search('195$',line):
             merke = 1

    file2.write(line)

file1.close()
file2.close()
Gruß,

momo

Verfasst: Samstag 21. März 2009, 13:03
von Hyperion
@momo:
- Es gibt True und False!
- Man sollte bei Dateinhandlings IOErrors abfangen oder eben mit "with" arbeiten.

Verfasst: Samstag 21. März 2009, 13:41
von hendrikS
Hier noch mal mein Vorschlag vervollständigt. Kommentare hinsichtlich try/except sollten noch berücksichtigt werden:

Code: Alles auswählen

fd1 = open('in.txt')
fd2 = open('out.txt','w')

lines = fd1.readlines()

fd2.write(lines[0])

for l1,l2 in zip(lines,lines[1:]):
    if l1[-4:] == '195\n':

        l2=l2.replace(' 2\n','77\n').replace(' 1\n','70\n')

    fd2.write(l2)

fd1.close()
fd2.close()

Verfasst: Samstag 21. März 2009, 13:50
von HWK
Statt

Code: Alles auswählen

if l1[-4:] == '195\n':
besser

Code: Alles auswählen

if l1.endswith('195\n'):
MfG
HWK

Verfasst: Samstag 21. März 2009, 14:08
von cofi
Außerdem sollte man nie ein kleines L zusammen mit Zahlen benutzen. ;)

Danke!

Verfasst: Samstag 21. März 2009, 15:30
von _johannes
Super. Vielen Dank für Eure Hilfe.

So wie hendrikS und HWK es vorgeschlagen haben, funktioniert es bestens.
Ich bin gerade noch dabei, mir mal die Funktionsweise zu verinnerlichen.

Mal ne ganz allgemeine Frage:
Wie kommt man auf sowas? Reine Erfahrung? Habt Ihr sämtliche Pythonbefehle im Kopf?
Ich habe zwar mehrere Python-Bücher vor mir liegen, da steht das natürlich auch drin, aber ich weiss eben meist nicht nach was ich suchen soll.

Grüße, Johannes.

Re: Danke!

Verfasst: Samstag 21. März 2009, 16:31
von Leonidas
_johannes hat geschrieben:Wie kommt man auf sowas? Reine Erfahrung? Habt Ihr sämtliche Pythonbefehle im Kopf?
Ich habe zwar mehrere Python-Bücher vor mir liegen, da steht das natürlich auch drin, aber ich weiss eben meist nicht nach was ich suchen soll.
Nein, alle Befehle im Kopf haben ist total unnütz. Es macht ja keinen Sinn jeden Funktion der Stdlib zu kennen wenn man auch einfach in der Dokumentation nachschauen könnte. Es hilft, sich irgendwelchen interessanten Code anzusehen und nachzuvollziehen. Oft ist es sinnvoll etwa am Interpreter-Prompt Code einzutippen und ausprobieren was man so machen könnte.
Ich fand es auch immer schön, die "What's new in Python X.Y"-Dokumente zu lesen und zu überlegen wozu die neu eingeführen Features nützlich sein könnten.

Anschlussfrage

Verfasst: Sonntag 22. März 2009, 15:11
von _johannes
So, ich habe mir das ganze angeschaut und weiter umgesetzt, hänge aber wieder (jetzt aber an nem anderen Punkt).

Die Ersetzungen sind noch komplizierter:
Hier erstmal ein Ausschnitt aus der zu bearbeitenden Datei, damit lässt es sich leichter erklären:

Code: Alles auswählen

0.00400000 62
    0.000      3075  __
    6.160     98555   2
    8.192    130051  99
    8.936    141583 141
   10.856    171343   1
   14.896    233963 195
   15.396    241713   2
   17.400    272775  99
   18.148    284369 255
   20.068    314129  14
   24.200    378175 195
   24.488    382639   1
   26.492    413701  99
   27.224    425047 101
   29.144    454807   3
   33.532    522821 195
   34.208    533299   1
   36.220    564485  99
   36.952    575831 251
   38.872    605591   6
   42.996    669513 195
   43.924    683897   2
Es soll nun, wenn am Zeilenende eine 141 steht, die Zahl, die nach der auf die 141\n folgende 195\n steht, ersetzt werden. Wenn dort eine 1\n steht, soll diese durch 77\n ersetzt werden, wenn dort eine 2\n steht, soll diese durch 70\n ersetzt werden.
Ich muss also über Vierpäckchen iterieren. Das habe ich soweit auch hinbekommen.
Jetzt wird's noch einen Schritt komplexer und da hakt's:
Es soll jetzt nicht nur nach den 141ern geschaut werden, sondern nach allen sogenannten 'incorrect conditions' (das sind 141,142,151,152,241,242,251 und 252). Im Auschnitt oben würde also die 1\n in Zeile 24 durch 77\n ersetzt, nicht aber die in Zeile 14 und 19.

Eigentlich ganz klar, dachte ich, ich iteriere über eine Liste in der die 'incorrect conditions' stehen:

Code: Alles auswählen

incorrect = ['141\n','142\n','151\n','152\n','241\n','242\n','251\n','252\n']
#correct = ['144\n','155\n','244\n','255\n','101\n','102\n','201\n','202\n']

fd1 = open('text.txt')
fd2 = open('text.txt2','w')



lines = fd1.readlines()
for i in lines [0:3]:
	fd2.write(i)
	
for a in incorrect:
	for l1,l2,l3,l4 in zip(lines, lines[1:], lines[2:], lines[3:]):
		if l1.endswith(a) and l3.endswith('195\n'):
			l4=l4.replace(' 2\n','77\n').replace(' 1\n','70\n')
		fd2.write(l4)

fd1.close()
fd2.close()	
Leider ist das Ergebnis das gleiche, wie ohne die for a in incorrect-Schleife. Ich blicke hier irgendwie die richtige Verschachtelung nicht, oder? Ich habe schon mehrere Varianten ausprobiert… mit sehr mäßigem Erfolg.
Könnt Ihr mir sagen, wie das geht?

Grüße,
Johannes

Verfasst: Sonntag 22. März 2009, 15:51
von hendrikS
Laß die äußere Schleife weg und ersetze die Bedingung wie folgt:

(Ungetestet!!)

Code: Alles auswählen

if l1[-4:] in incorrect and l3.endswith('195\n'):
Außerdem noch mal Kommentare von cofi berücksichtigen. Die Variablenbezeichnung war meinerseits nicht besonders glücklich.

Jau

Verfasst: Sonntag 22. März 2009, 18:29
von _johannes
Super! So funzt es.

…auch wenn ich mich immer noch frage warum meine Version das nicht gemacht hat.

Auf jeden Fall vielen Dank nochmal.

Grüße,
Johannes