Text zwischen zwei bestimmten Werten 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.
Antworten
ernestovaya
User
Beiträge: 7
Registriert: Dienstag 16. Oktober 2012, 13:47

Hallo,

ich hab ein Problem, auf das ich trotz Google nicht wirklich komme. Und zwar möchte ich in einem HTML-Dokument den Text zwischen den Zeilen die mit "<com>" und "</com>" beginnen, mit einem Text aus einer anderen Datei ersetzen.

also quasi:
<com>
Blindtext
Blindtext
</com>

soll ersetzt werden durch
<com>
neu
neu
</com>

mit der re.compile -Methode tut sich allerdings gar nichts...Vielleicht kann mir ja hier jmd zeigen, wo mein Fehler liegt. Schon mal Danke für Eure Antworten!

Code: Alles auswählen

                chop = re.compile('<com>.*?</com>', re.DOTALL)
                html = open(''+fileroot+'/'+shortname[j]+'.html', 'r')
                data = html.read()
                html.close()
                chopped=chop.sub('',data)
                html = open('data', 'w')
                html.write(chopped)
                with open(''+filedir[j]+'/'+shortname[j]+''+extension[j]+'.note') as text:
                    html.write('<com>\n')
                    for row in text:
                        html.write('<p> '+row+'</p>\n')
                    html.write('</com>\n')
                html.close()
Zuletzt geändert von cofi am Freitag 19. Juli 2013, 18:47, insgesamt 1-mal geändert.
Grund: Syntax-Highlighting gesetzt
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Du willst den Match von `chop` nicht loeschen, sondern durch den anderen Text ersetzen, d.h. du solltest den anderen Text als Ersetzung uebergeben:

Code: Alles auswählen

chop = re.compile('<com>.*?</com>', re.DOTALL)
with open('' + fileroot+'/'+shortname[j]+'.html') as html:
    data = html.read()

with open(''+filedir[j]+'/'+shortname[j]+''+extension[j]+'.note') as text:
    replacement = '<com>\n%s</com>\n' % (''.join('<p>%s</p>\n' % row for row in text))

with open('data', 'w') as html:
    html.write(chop.sub(replacement, data))
Und dann solltest du wahrscheinlich auf `for directory, basename, extension in zip(filedirs, shortnames, extensions)` arbeiten statt mit diesem gruseligen Index....
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

ernestovaya hat geschrieben:ich hab ein Problem, auf das ich trotz Google nicht wirklich komme. Und zwar möchte ich in einem HTML-Dokument den Text zwischen den Zeilen die mit "<com>" und "</com>" beginnen, mit einem Text aus einer anderen Datei ersetzen.
Verwende dafür passende Tools wie lxml oder BeautifulSoup. An HTML-/XML-Dokumenten sollte man nicht mit Stringoperationen oder regulären Ausdrücken rumfummeln.
Dami123
User
Beiträge: 225
Registriert: Samstag 23. Februar 2013, 13:01

Zu dem Thema fällt mir auch noch ein Problem ein, welches ich zwischenzeitlich liegen lassen hab.
Ich arbeite mir "mechanize.Browser()" und füttere Websiten mit Infos, die ich sonst mit der Hand eingeben müsste.
Um dabei Werte Funktionen, die "hidden" sind zu geben reicht ".form.set_all_readonly(False)", welches auch erlaubt "readonly" Funktionen Werte zu übergeben.

Nun bin ich aber auf eine Website gestoßen, die Funktionen beinhaltet, welche "disabled" sind. Leider supportet die letzte Version von mechanize nicht das verändern dieser Werte. Sowas wie ".form.set_all_disabled(False)" gibts noch nicht.
Bin später auf eine Variante gestoßen, welche mit lxml funktioniert und den code verändert, theoretisch auch "disabled"-Werte manipuliert.
Weiß da jemand genaueres drüber?

Auch gelesen hab ich von einem script für "mechanize" welches hinhalten soll, bis ein offizielles update kommt.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

@Dami123: Das Problem ist komplett irrelevant zu dem aktuellen. Erstelle bitte ein neues Thema.
Dami123
User
Beiträge: 225
Registriert: Samstag 23. Februar 2013, 13:01

Ja eig. schon :roll:

Hab aber eine Lösung gefunden!
Das ich das übersehen hab, ist mehr als Peinlich ^^
Man kann den einzelnen Controls den Wert "disabled" zuweisen.

Code: Alles auswählen

control.disabled = True
Quelle: http://www.pythonforbeginners.com/cheat ... eat-sheet/
ernestovaya
User
Beiträge: 7
Registriert: Dienstag 16. Oktober 2012, 13:47

Hallo cofi,

vielen Dank, da war mein Denkfehler! Ich habe jetzt nur noch ein Problem. Und zwar wenn ich den "chop.sub(replacement, data" printe, dann gibt er mir den richtigen Inhalt aus. Allerdings wird dies nicht in die eigentliche Zieldatei geschrieben. Woran könnte das liegen? Ist "html" vielleicht schon automatisch geschlossen worden (wegen "with open...")

Lieben Dank!
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Zeig doch bitte den Quelltext den du verwendest, alles andere ist nicht zielfuehrend.

Eines kann ich dir aber sagen: Wuerdest du versuchen in ein Dateiobjekt zu schreiben, das geschlossen ist, dann bekaemst du eine Exception.
ernestovaya
User
Beiträge: 7
Registriert: Dienstag 16. Oktober 2012, 13:47

falls du mit quelltext den code meinst, so ist dieser ziemlich dem bereits geposteten und deinem lösungsvorschlag gleich:

Code: Alles auswählen

if os.path.exists(''+fileroot+'/'+shortname[j]+''+extension[j]+'.note_mod.date'):
                notenow = (os.path.getmtime(''+filedir[j]+'/'+shortname[j]+''+extension[j]+'.note'))
                with open(''+fileroot+'/'+shortname[j]+''+extension[j]+'.note_mod.date') as n:
                    notedate=str(n.readline())
                if notenow == notedate:
                    pass
                else:
                    chop = re.compile('<com>.*?</com>', re.DOTALL)
                    with open(''+fileroot+'/'+shortname[j]+'.html') as html:
                        data = html.read()
                    with open(''+filedir[j]+'/'+shortname[j]+''+extension[j]+'.note') as text:
                        replacement = '<com>\n%s</com>\n' % (''.join('<p>%s</p>\n' % row for row in text))
                    with open('data', 'w') as html:
                        html.write(chop.sub(replacement, data))
                        print chop.sub(replacement, data)
und eben bei print gibt er den richtigen Text (also bisheriger HTML code inklusive ersetzter Bereich) aus, in die als html geöffnete file schreibt er diesen Inhalt jedoch nicht....danke schon mal für Hinweise!!
BlackJack

@ernestovaya: Das kann nicht sein. In die Datei wird genau das gleiche geschrieben wie auch mit ``print`` ausgegeben wird, also muss da auch das gleiche drin stehen. Es wird allerdings in eine Datei mit dem Namen 'data' geschrieben, kann es sein, dass das nicht so sein sollte und Du in der falschen Datei nach dem Ergebnis schaust?

Das zusammensetzen der Dateipfade ist übrigens mehr als gruselig. Was denkst Du zum Beispiel was dass konkatenieren einer leeren Zeichenkette für einen Effekt hat? Das hier ist Python und nicht Java oder JavaScript. Pfade setzt man mit `os.path.join()` zusammen. Unschön ist auch das `j` und dass manche Pfade mehrfach so umständlich erstellt werden. `shortname` und `extension` sollten nicht zwei Listen sein, sondern eine.
BlackJack

@ernestovaya: Es gibt noch einen Fehler in dem Quelltext. Im Grunde sogar zwei. Zum einen wird *immer* der ``else``-Zweig betreten weil Du eine Zahl mit einer Zeichenkette vergleichst und die niemals gleich sind. Und man sollte den Ersetzungstext „escapen”, denn auch dort gibt es Zeichenfolgen mit einer besonderen Bedeutung für reguläre Ausdrücke. Ich komme dann auf so etwas hier (ungetestet):

Code: Alles auswählen

        # 
        # TODO Too nested.  Split method/function.
        # TODO Better name for `data`.
        # 
        com_re = re.compile(r'<com>.*?</com>', re.DOTALL)
        for short_name, extension, file_dir in data:
            base_filename = short_name + extension
            date_filename = os.path.join(
                root_path, base_filename + '.note_mod.date'
            )
            if os.path.exists(date_filename):
                with open(date_filename) as date_file:
                    timestamp = int(next(date_file))
                note_filename = os.path.join(file_dir, base_filename + '.note')
                note_modified_timestamp = os.path.getmtime(note_filename)
                if note_modified_timestamp != timestamp:
                    with open(
                        os.path.join(root_path, short_name + '.html')
                    ) as html_file:
                        content = html_file.read()
                    # 
                    # XXX Not robust against HTML markup in `note_file`.
                    # 
                    with open(note_filename) as note_file:
                        replacement = '<com>\n{0}</com>\n'.format(
                            ''.join(
                                '<p>{0}</p>\n'.format(line)
                                for line in note_file
                            )
                        )
                    with open('data', 'w') as html_file:
                        html_file.write(
                            com_re.sub(re.escape(replacement), content)
                        )
ernestovaya
User
Beiträge: 7
Registriert: Dienstag 16. Oktober 2012, 13:47

Alles klar, vielen vielen dank an euch! Es hat jetzt geklappt.

@BlackJack. Ich habe deinen Rat befolgt und das escape mit eingebaut. Aber den Sinn habe ich nicht ganz verstanden bzw um was für Zeichenketten handelt es sich bspw.?

Viele Grüße
BlackJack

@ernestovaya: „Backreferences” wie \0, \1, \2, \g<3>, \g<some_name> und so weiter.
Antworten