RE

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
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

RE

Beitragvon jens » Mittwoch 29. Juni 2005, 13:19

Hab ein RE Problem. Ich möchte URL's in Texten zu einem echten HTML-Link machen. Allerdings allerdings soll der letzte Beispiellink ( "Das deutsche Python-Forum":http://www.python-forum.de ) davon unberührt bleiben!

Code: Alles auswählen

import re

txt = """http://keinserver.dtl
ftp://keinserver.dtl
http://www.python-forum.de
"Das deutsche Python-Forum":http://www.python-forum.de"""

print txt
print "="*80

print re.sub(
    r"""
        (http|ftp)://(\S+)
        (?uisx)""",
    r'<a href="\1://\2">\1://\2</a>',
    txt
    )
print "-"*80
#~ txt = " "+txt # Hiermit geht's...
print re.sub(
    r"""
        ([^:])
        (http|ftp)://(\S+)
        (?uimx)""",
    r'\1<a href="\2://\3">\2://\3</a>',
    txt
    )

Code: Alles auswählen

http://keinserver.dtl
ftp://keinserver.dtl
http://www.python-forum.de
"Das deutsche Python-Forum":http://www.python-forum.de
================================================================================
<a href="http://keinserver.dtl">http://keinserver.dtl</a>
<a href="ftp://keinserver.dtl">ftp://keinserver.dtl</a>
<a href="http://www.python-forum.de">http://www.python-forum.de</a>
"Das deutsche Python-Forum":<a href="http://www.python-forum.de">http://www.python-forum.de</a>
--------------------------------------------------------------------------------
http://keinserver.dtl
<a href="ftp://keinserver.dtl">ftp://keinserver.dtl</a>
<a href="http://www.python-forum.de">http://www.python-forum.de</a>
"Das deutsche Python-Forum":http://www.python-forum.de


Der letzte re.sub() geht zwar eigentlich schon, nur die erste URL wird dabei auch ausgeschlossen :( Nur wenn ich dem Textblock irgendein Zeichen vorsetzte geht's so wie ich es haben will... Aber das ist ein doofer Workaround...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Beitragvon BlackJack » Mittwoch 29. Juni 2005, 21:41

Das klappt nicht, weil Du als erstes ein Zeichen suchst, das nicht ':' ist und vor der ersten URL gar kein Zeichen steht. Darum hilft auch das voranstellen eines Leerzeichens.

Du brauchst einen Ausdruck, der zwar "match"t aber keine Zeichen verbraucht: eine negative lookbehind assertion. Die schaut nach dem "match"en nochmal zurück, ob vor dem Treffer eine bestimmte Zeichenkette nicht steht -- in dem Falle ein ':'.

Code: Alles auswählen

print re.sub(
     r"""
         (?<!:)
         (?P<url>(http|ftp)://(\S+))
         (?uimx)""",
     r'<a href="\g<url>"><\g<url></a>',
     txt
     )


Das Muster, was die URL erkennt, hat jetzt ausserdem einen Namen erhalten (<url>) damit kann man dann beim Ersetzen besser nachvollziehen was da ersetzt wird. Und wenn man das Muster oben ändert, z.B. Ausdrücke mit Klammern hinzufügt oder weglässt, dann muss man in Ersetzungstext die Numerierung nicht ändern.
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 29. Juni 2005, 21:57

Super! Danke... Bei dir ist allerdings ein Smilie drin ;) Jetzt nicht mehr:

Code: Alles auswählen

print re.sub(
     r"""
         (?<!:)
         (?P<url>(http|ftp)://(\S+))
         (?uimx)""",
     r'<a href="\g<url>"><\g<url></a>',
     txt
     )

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 29. Juni 2005, 22:10

Da ist auch noch ein kleiner Fehler, so geht's richtig:

Code: Alles auswählen

print re.sub(
     r"""
         (?<!:)
         (?P<url>(http|ftp)://(\S+))
         (?uimx)""",
     r'<a href="\g<url>">\g<url></a>',
     txt
     )

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Donnerstag 30. Juni 2005, 23:00

Ich hab da noch eine kniffelige RE Aufgabe für mein TinyTextile Parser, welches ich einfach nicht gelöst bekomme:

aus:

Code: Alles auswählen

text1
text2

text3
text4
Text *text* text
* Liste1
* eintrag2
* eintrag3

text
* Liste A
** Liste B

** liste
** liste


soll das werden:

Code: Alles auswählen

text1
text2

text3
text4
Text *text* text

* Liste1
* eintrag2
* eintrag3

text

* Liste A
** Liste B

** liste
** liste


Also es sollen zusätzliche Leerzeilen, zwischen einem Text-Block und einem List-Block eingefügt werden.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Donnerstag 30. Juni 2005, 23:19

jens hat geschrieben:Ich hab da noch eine kniffelige RE Aufgabe...

Hi jens!

Ist es auch OK, wenn du kein RE dafür verwendest?

Code: Alles auswählen

def listen_freistellen(mytext):
   quelle = mytext.split("\n")
   ziel = list()
   
   for line in [line.strip() for line in quelle]:
      if line.startswith("* "):
         if len(ziel) > 0:
            if ziel[-1] != "" and not(ziel[-1].startswith("* ")):
               ziel.append("")
      ziel.append(line)
   
   return "\n".join(ziel)
   
   
oldtext = \
"""text1
text2

text3
text4
Text *text* text
* Liste1
* eintrag2
* eintrag3

text
* Liste A
** Liste B

** liste
** liste"""

print listen_freistellen(oldtext)


lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
joe

Beitragvon joe » Donnerstag 30. Juni 2005, 23:28

jens hat geschrieben:Ich hab da noch eine kniffelige RE Aufgabe für mein TinyTextile Parser, welches ich einfach nicht gelöst bekomme:


Die eine leerzeile (drittletzte zeile) ist hässlich.

re.sub(r"(^[^*\n].+?$)(\n^\*(?m))",r"\1\n\2",text)

joe
Gast

Beitragvon Gast » Donnerstag 30. Juni 2005, 23:38

joe hat geschrieben:re.sub(r"(^[^*\n].+?$)(\n^\*(?m))",r"\1\n\2",text)
Was ich 5 min später nicht mehr verstehe, ist schlecht.

Also hier auch eine lösung ohne re:

Code: Alles auswählen

zz = text.split('\n')
for i,z in enumerate(zz[1:]):
    if z.startswith('*') and len(zz[i-1]) and not zz[i-1].startswith('*'):
        zz[i-1] += "\n"
text = '\n'.join(zz)

joe
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Freitag 1. Juli 2005, 08:08

Danke für eure Mühen... Ich werde die Version von joe nehmen. Das kann ich besser in TinyTextile einbauen.
Wenn man es ein wenig aufbröselt, wird die RE-Regeln auch verständlicher:

Code: Alles auswählen

print re.sub(
    r"""
        (^[^*\n].+?$) # Text-Zeile vor einer Liste
        (\n^\*) # Absatz + erstes List-Zeichen
        (?uimx)
    """,
    r"\1\n\2",
    txt
    )

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder