Strings "bearbeiten" mit Python

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
man-draker
User
Beiträge: 1
Registriert: Sonntag 8. September 2002, 21:56
Wohnort: Langenhagen

Hallo Leute,

nicht nur hier bin ich neu, auch was Python angeht. Daher stehe vor einem Problem, dass jeden Fortgeschrittenen wahrscheinlich den Kopf schütteln lässt:

Gegeben ist der Eintrag aus einem Mehrzeilen-Feld in einem HTML-Formular.
Dieser enthält unter anderem Zeilenschaltungen.
Das mag aber das Modul FlatDB, mit dessen Hilfe die Daten gespeichert werden sollen, garnicht. (Jedenfalls knallt es beim Wieder-Auslesen.)

Nun ist der Feldinhalt, wenn ich ihn aus cgi.userinput heraushole im Format string.
Also, als alter Pascal-Programmierer: String auf Zeichen kleiner SPACE gescannt und alle solchen durch Leerzeichen ersetzt

Nun ist aber der Typ string bei Python nicht veränderbar. :-(
Also schwupps in eine Liste konvertiert, diese bearbeitet und zurück in einen string konvertiert. Etwas umständlich und -- jetzt kommts -- das Ergebnis ist unbrauchbar. Aus "123" wird ['1','2','3'] und das ist nicht so ganz das, was ich mir vorstelle.

Ich suche also einen Weg
- entweder doch an Strings zu manipulieren oder
- aus einer Liste einen brauchbaren String zu machen.

Wer weiß Rat?
joerg
User
Beiträge: 188
Registriert: Samstag 17. August 2002, 17:48
Wohnort: Berlin
Kontaktdaten:

man-draker hat geschrieben: ...
Ich suche also einen Weg
- entweder doch an Strings zu manipulieren oder
- aus einer Liste einen brauchbaren String zu machen.

Wer weiß Rat?
Wie Du richtig erkannt hast, sind Strings in sich nicht veränderbar. Aber mußt Du wirklich genau diesen String verändern? Wenn nein, mache es doch so:

Code: Alles auswählen

>>> x = 'Hallo\nDu da!'
>>> print x
Hallo
Du da!
>>> x = x.replace('\n', ' ')
>>> print x
Hallo Du da!
x ist jetzt auch der geänderte String, der ursprüngliche wurde durch die Referenzzählung einfach weggeworfen - alles ok!

Und zum Problem Liste->String:

Code: Alles auswählen

>>> l = ['L', 'i', 's', 't', 'e']
>>> import string
>>> print string.join(l)
L i s t e
>>> print string.join(l, '')
Liste
>>> print string.join(l, '-')
L-i-s-t-e
join fügt zusammen, und setzt ein Trennzeichen ein. Da dieses auf das Leerzeichen voreingestellt ist, muß man explizit einen leeren String angeben, um kein Trennzeichen zu bekommen.
RicmanX
User
Beiträge: 69
Registriert: Donnerstag 29. August 2002, 17:10
Wohnort: Erfurt
Kontaktdaten:

Aus meinem Alpha-Status Gästebuch:
(meinst doch ne <textarea>!?)

Code: Alles auswählen

import re, cgi

puffer = cgi.FieldStorage()

kommentar = puffer["kommentar"].value
kommentar = re.sub("\r\n", "<br>", kommentar)
d.h.: substituiere (ersetze) alle "\r\n" (hab mir mal den Dictionary puffer voll anzeigen lassen und da sind das halt die Enter, nich nur die "\n") durch "<br>" und zwar beim Inhalt von kommentar.
piddon
Gründer
Beiträge: 410
Registriert: Dienstag 30. Juli 2002, 18:03
Wohnort: Oestrich-Winkel
Kontaktdaten:

\r\n setzen, soweit ich weiss, nur Browser die auf Windows laufen. Wenn du Netscape o.ä. unter Linux benutzt, so hast du nur ein \r (oder war es nur \n? :) ) Also besser ist beides einzeln, bei Bedarf zu ersetzen.
irc: #python.de @ irc.freenode.net | [url=http://pythonwiki.pocoo.org]python-wiki[/url] | [url=http://www.pythonwiki.de/PythonDeForum/Faq]python-forum FAQ[/url]
Gast

Zuerst einmal Dank an alle Hilfesteller.

1. Dass die Liste als String so seltsam aussah lag im Zweifel an meinem falschen Verstehen der Funktion str(), die halt keine liste -> string Funktion ist.

2. Die Antwort von joerg ist die exakt auf die gestellte Frage passende.

3. Die Antwort von RicmanX ist die, die das konkrete Problem am elegantesten (aus Sicht des Kodierenden) löst. Diese habe ich vorerst umgesetzt (und sie funktioniert).

4. Wenn die Benutzer es schaffen weitere unverdauliche Zeichen in die Eingabe zu packen, komme ich eventuell auf Methode Eins zurück, denn:

5. Weil zumindest der Konqueror (zu meiner Überraschung) einen Druck auf die Enter-Taste mit dem Einfügen von x0d x0a (oder \r\n) beantwortet, es andere Browseraber durchaus anders machen könnten (\n bei UNIX und ich fürchte \r beim Mac) suche ich jetzt zuerst einmal nach \r\n und anschließend sicherheitshalber noch einmal nach \n.
Hier das Ergebnis:

Code: Alles auswählen

def delEnter(such):
	s = re.sub("\r\n", "<br>", such)
	s = re.sub("\n", "<br>", s)
	return s
Ihr habt mir jedenfalls um die Klippe, an der ich hängen geblieben bin, herum geholfen. Dafür vielen Dank.
RicmanX
User
Beiträge: 69
Registriert: Donnerstag 29. August 2002, 17:10
Wohnort: Erfurt
Kontaktdaten:

Code: Alles auswählen

def delEnter(such): 
    return re.sub(os.linesep, "<br>", such)
:)
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
RicmanX hat geschrieben:

Code: Alles auswählen

def delEnter(such): 
    return re.sub(os.linesep, "<br>", such)
Was bringt Dir das? Das Script unter Win ausgeführt ersetzt keine "\n" ohne "\r"' davor und unter Unix ausgeführt wird bei "\r\n" nur das "\n" ersetzt.

Jan
joerg
User
Beiträge: 188
Registriert: Samstag 17. August 2002, 17:48
Wohnort: Berlin
Kontaktdaten:

Hallo Leute,

Ich persönlich finde re etwas übertrieben, um einzelne Zeichen oder klar definierte Zeichenketten zu suchen und zu ersetzen, da die String-Methoden das auch können, und zwar deutlich schneller. Bei mir liefert der folgende ganz einfache Test:

Code: Alles auswählen

import re, time
s = 'abcdefg' * 100
t = time.time()
for i in range(1000):
    s = re.sub('a', 'X', s)
    s = re.sub('X', 'a', s)
print time.time() - t
t = time.time()
for i in range(1000):
    s = s.replace('a', 'X')
    s = s.replace('X', 'a')
print time.time() - t
ungefähr einen Geschwindigkeitsvorteil vom Faktor 10 zugunsten der String-Methode! :D

Selbst wenn die Zeitmessung nicht so genau ist, und auf anderen Systemen vielleicht der Faktor nicht so hoch ist, sehe ich keinen Vorteil der re-Methoden, solange man reguläre Ausdrücke nicht wirklich braucht. Die Strings und ihre Methoden hat man immer, re muß man erst importieren.

Und bei der Ersetzungsmethode bin ich eher ein Fan der Trennung von Daten und Funktion, ich würde wahrscheinlich eine leicht erweiterbare Ersetzungstabelle und eine allgemeine Ersetzungsfunktion definieren, aber das ist wirklich Geschmackssache: :wink:

Code: Alles auswählen

transTab = (('\r', ''),('\n', '<br>'),('bla', 'fasel'))

def translate(s, tab=transTab):
    for old, new in tab:
        s = s.replace(old, new)
    return s

print translate('Dies \r\n ist \n ein Text')
Dies <br> ist <br> ein Text
RicmanX
User
Beiträge: 69
Registriert: Donnerstag 29. August 2002, 17:10
Wohnort: Erfurt
Kontaktdaten:

Voges hat geschrieben:Hallo!
RicmanX hat geschrieben:

Code: Alles auswählen

def delEnter(such): 
    return re.sub(os.linesep, "<br>", such)
Was bringt Dir das? Das Script unter Win ausgeführt ersetzt keine "\n" ohne "\r"' davor und unter Unix ausgeführt wird bei "\r\n" nur das "\n" ersetzt.

Jan
Unix hat nur "\n", Windows hat "\r\n" usw.
Und das os Modul fragt nach dem OS und setzt entsprechend den Richtigen LineSeparator.
Da eine <textarea> immer nur diese OS spezifischen Zeilenumbrüche verwendet und es hier um HTML geht, ist es ja das Ziel mit möglich wenigst Abfragen/Aktionen diesen Zeilenumbruch zu ersetzen. Und genau das macht diese Funktion: je nach OS (bzw. mit Browser) wird der Zeilenumbruch zu nem HTML Zeilenumbruch gewandelt. Wozu unbedingt etwas universelles, aber langsameres machen, womit das Script eh nie konfrontiert wird?
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
RicmanX hat geschrieben: Unix hat nur "\n", Windows hat "\r\n" usw.
Und das os Modul fragt nach dem OS und setzt entsprechend den Richtigen LineSeparator.
Ich verstehe es immer noch nicht. Es geht doch um ein CGI-Script, also ein Script, das auf dem Server läuft. Was hilft es Dir zu wissen, wie der Lineseperator des Server-OS lautet (bei Linux z.B. "\n"), wenn Dir der Client (sprich Browser) was anderes im Textarea-Text für Umbrüche vorsieht (bei Netscape/Win z.B. "\r\n"). Ein re.sub(os.linesep, "<br>", such) macht dann aus "bla\r\nblub" ein "bla\r<br>blub" (hab' ich getestet). Vielleicht reden wir aber auch von verschiedenen Sachen ;-)

Jan
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Voges hat geschrieben: Und das os Modul fragt nach dem OS und setzt entsprechend den Richtigen LineSeparator.
Mal ne bescheidene Zwischenfrage, was passiert, wenn die Datei auf einen Server hochgeladen wird und das Script auf dem Server ausgeführt wird? Dann gibt es vier Möglichkeiten: WW, WU, UW, UU (1.Stelle OS Server, 2. Stelle OS Client). Dieses Script dürfte doch nur bei Kombination WW oder UU greifen.

Gibts Alternativen? Unter Linux / Unix steht ja mit file ein entsprechendes Programm zur Verfügung. Bei Windows ist mir derartiges nicht bekannt.

Andererseits, ist es wichtig, dass ich hier nach OS unterscheide? Enternen wir doch erst mal Ballast (/r) und ersetzen dann /n. Sollte doch Sauber sein oder?

Hans
RicmanX
User
Beiträge: 69
Registriert: Donnerstag 29. August 2002, 17:10
Wohnort: Erfurt
Kontaktdaten:

Ich weiß nicht ob entfernen so gut ist, schließlich kann es eine beliebige Eingabe sein. Da ist ersetzen irgendwie schon besser.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Also ein /r ohne /n kenne ich nur von Druckdateien, nämlich bei Nadelprintern. hallo Welt/rhallo Welt sorgt dafür, dass der Wagen einmal nich links gefahren wird ohne dabei einen Zeilenvorschub zu machen und die Zeile dann nochmal zu Drucken. Das ganze erscheint dann FETT

Ich denke mal, das es in diesem Fall nicht um eine Druckdatei handelt. Und wenn die Datei nicht verändert werden darf, dann arbeite doch mit einer Kopie.

Wie war das eigentlich mit Macs, BeOS und co? /n oder /r/n ?

Hans
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi hans,

Win = /r/n
Unix = /n
Mac = /r
Antworten