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.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

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
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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 
     )

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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
     )

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

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

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

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
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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
    )

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten