Seite 1 von 1
Halbwegs einfachen Ausdruck finden möglichst ohne re?
Verfasst: Freitag 21. Oktober 2005, 07:34
von henning
Wie kann ich am schnellsten einen Docstring nach einem Ausdruck der Form "<<XXX>>" durchsuchen, wobei XXX ein unbekannter String ist (welche natürlich nicht ">>" enthält) und nicht bekannt ist, ob der Docstring meinen Ausdruck überhaupt enthält?
Ist es in dem Fall schneller mit re's oder mit string-eigenen Funktionen?
Das "<<" und ">>"-Geraffel kann ich auch beliebig ändern, ich will nur einen bestimmten String innerhalb meines Docstrings markieren, so dass ich ihn mit möglichst wenig Laufzeitaufwand wieder rausfischen kann.
Verfasst: Freitag 21. Oktober 2005, 08:46
von jens
In PyLucid gibt es den sourcecode_parser.py:
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Source Code Parser
Based on J�en Hermann's "MoinMoin - Python Source Parser"
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298/
"""
__version__="0.2.0"
__history__="""
v0.2.0
- Einige Optimierungen
- Bug mit den speziellen Zeilenumbrüche mit \ am ende (kein Zeilenumbruch) behoben
v0.1.0
- aus SourceCode.py Plugin entnommen, damit er auch f�tinyTextile genutzt werden kann
"""
import sys, cgi, cStringIO, \
keyword, token, tokenize
token.KEYWORD = token.NT_OFFSET + 1
class python_source_parser:
def parse( self, raw_txt ):
"""
Parse and send the colored source.
"""
self.special_not_newline = False
self.raw = raw_txt.expandtabs()
# store line offsets in self.lines
self.lines = [0, 0]
pos = 0
while 1:
pos = self.raw.find( '\n', pos ) + 1
if not pos: break
self.lines.append( pos )
self.lines.append( len(self.raw) )
# parse the source and write it
self.pos = 0
text = cStringIO.StringIO( self.raw )
try:
tokenize.tokenize(text.readline, self)
except tokenize.TokenError, ex:
msg = ex[0]
line = ex[1][0]
print "<h3>ERROR: %s</h3>%s\n" % (
msg, self.raw[self.lines[line]:]
)
print "<br />\n"
def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
""" Token handler.
"""
# calculate new positions
oldpos = self.pos
newpos = self.lines[srow] + scol
self.pos = newpos + len(toktext)
# Patch for special not newline with \
if line.endswith("\\\n") and toktype!=tokenize.COMMENT:
self.special_not_newline = True
elif self.special_not_newline == True:
self.special_not_newline = False
print "\\<br />\n"
# handle newlines
if toktype in (token.NEWLINE, tokenize.NL):
sys.stdout.write( '<br />\n' )
return
# Spaces
if newpos > oldpos:
sys.stdout.write(" " * (newpos-oldpos))
if toktext=="":
return
# map token type to a color group
if token.LPAR <= toktype and toktype <= token.OP:
toktype = token.OP
elif toktype == token.NAME and keyword.iskeyword(toktext):
toktype = token.KEYWORD
# Text Escapen
toktext = cgi.escape( toktext )
# Non-Breaking-Spaces
toktext = toktext.replace(" "," ")
# Zeilenumbrüche umwandeln
toktext = toktext.replace("\n","<br />\n")
if toktype==token.NAME:
sys.stdout.write(toktext)
else:
sys.stdout.write('<span class="t%s">%s</span>' % (toktype,toktext))
#~ print "\n>>>",toktype
if __name__ == '__main__':
python_source_parser().parse(open(__file__).read())
Wenn du die __call__ Methode umschreibst, kannst du dammit nur DocStrings rausfiltern. Im Weiteren Schritt, kannst du dann nach deinen Markierungen Suche...
Verfasst: Freitag 21. Oktober 2005, 08:55
von mawe
Hi!
Also das Muster rausfiltern würde ich schon mit einer Regex machen. Mit den string-Funktionen fällt mir auf die Schnelle keine Lösung ein, die einfach und schnell sein sollte. Und re's sind ja auch nicht
so langsam

Schneller programmiert ist auf jedenfall die Version mit re
Gruß, mawe
Verfasst: Freitag 21. Oktober 2005, 09:14
von Francesco
Vielleicht so in etwa:
Code: Alles auswählen
a = "ababa<<teststring1>>cbcbc<<teststring2>>dcdc"
lastfoundindex = 0
s1 = '<<'
s2 = '>>'
found = []
while 1:
lf1 = a.find(s1, lastfoundindex) + len(s1)
lf2 = a.find(s2, lastfoundindex)
if lf1 > -1 and lf2 > -1 and lf1 < lf2:
found.append (a[lf1:lf2])
lastfoundindex = lf2 + 1
else:
break
print "Strings found:"
for s in found:
print s
Verfasst: Freitag 21. Oktober 2005, 11:34
von henning
Vielleicht hätte ich dazu sagen sollen, dass der Ausdruck höchstens einmal vorkommen soll, da die docstrings nicht von den endnutzern manipuliert werden kann ich schon davon ausgehen, dass das auch eingehalten wird.
Von daher hätte ich jetzt überlegt, evtl. mit str.find ranzugehen und den linken und rechten delimiter einzeln zu suchen.
Wobei mir gerade in meinem Bsp auffällt, dass ">>" eine ungünstige Wahl ist, wenn z.B. doctest im Spiel ist...