Zahlen in Datei ersetzen

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

Zahlen in Datei ersetzen

Beitragvon _johannes » Samstag 21. März 2009, 01:41

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=] 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[/code]

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=]
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())
[/code]

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
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Beitragvon Dauerbaustelle » Samstag 21. März 2009, 01:51

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
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Beitragvon hendrikS » Samstag 21. März 2009, 01:59

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.
momo
User
Beiträge: 9
Registriert: Donnerstag 19. März 2009, 17:52

Beitragvon momo » Samstag 21. März 2009, 12:56

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
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Beitragvon Hyperion » Samstag 21. März 2009, 13:03

@momo:
- Es gibt True und False!
- Man sollte bei Dateinhandlings IOErrors abfangen oder eben mit "with" arbeiten.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Beitragvon hendrikS » Samstag 21. März 2009, 13:41

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()
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Beitragvon HWK » Samstag 21. März 2009, 13:50

Statt

Code: Alles auswählen

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

Code: Alles auswählen

if l1.endswith('195\n'):
MfG
HWK
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Beitragvon cofi » Samstag 21. März 2009, 14:08

Außerdem sollte man nie ein kleines L zusammen mit Zahlen benutzen. ;)
Benutzeravatar
_johannes
User
Beiträge: 20
Registriert: Montag 19. Juni 2006, 17:37

Danke!

Beitragvon _johannes » Samstag 21. März 2009, 15:30

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.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Re: Danke!

Beitragvon Leonidas » Samstag 21. März 2009, 16:31

_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.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
_johannes
User
Beiträge: 20
Registriert: Montag 19. Juni 2006, 17:37

Anschlussfrage

Beitragvon _johannes » Sonntag 22. März 2009, 15:11

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=]
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
[/code]

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
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Beitragvon hendrikS » Sonntag 22. März 2009, 15:51

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

Jau

Beitragvon _johannes » Sonntag 22. März 2009, 18:29

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

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder