Das eigentliche Matchen läuft in zwei Zeilen, der Rest ist nur, damit das Programm hübsch verwendet werden kann 

Code:
# -*- encoding: utf-8 -*-
import re
"""
Quiz #1
Der Fuzzy Matcher erledigt die geforderte Aufgabe eigentlich in einem
Zwei-Zeiler.
regex = re.compile( "(.*)%s(.*)" % \
"(.*?)".join( "%s" % re.escape(x) for x in query if x.strip() ), \
re.IGNORECASE )
query_matches = regex.match( word ) != None )
Am Beispiel JFK:
Der Suchbegriff wird in einen regulären Ausdruck umgewandelt,
indem zwischen alle Buchstaben beliebige Zeichen gematched werden können.
(greedy für die Übersicht beim Highlight, Whitespaces weggelassen)
JFK wird also zu: (.*?)J(.*?)F(.*?)K(.*)
Dieser Ausdruck wird nun auf das zu prüfende Wort angewand, und, wenn er
matched, dann haben wir was gefunden! =)
"""
class FuzzyMatcher( object ):
"""
Initialisiert einen FuzzyMatcher mit einem gegebenen Suchbegriff.
"""
def __init__( self, query, case_sensitive = False ):
self._query = query
self._regex = re.compile( "(.*?)%s(.*)" % \
"(.*?)".join( "%s" % re.escape(x) for x in query if x.strip() ), \
0 if case_sensitive else re.IGNORECASE )
"""
Prüft ob 'word' auf den Suchbegriff passt und gibt je nach Ergebnis
True oder False zurück
"""
def match( self, word ):
return self._regex.match( word ) != None
""" Wenn 'word' als ein Suchergebnis identifiziert wurde,
wo werden alle Vorkommen des Suchbegriffes markiert..
Falls nicht, wird ein ValueError geworfen
"""
def highlight( self, word ):
match = self._regex.match( word )
if not match:
raise ValueError( "word does not match the query" )
query = self._query
result = []
is_open = False
groups = match.groups()
for index in range( len( groups ) ):
this = groups[index]
next = groups[index+1] if index < len( groups ) - 1 else None
# Wir befinden uns nicht zwischen zwei
# aufeinander folgenden, gefundenen Buchstaben
if this:
# die Markierung ist noch offen. Wir schließen sie
if is_open:
result.append( ">" )
is_open = False
# Wir kopieren ein Stück Text, was zwichen > und < vorkommt
# in unser Ergebnis
result.append( this )
# Wir sind nicht am Ende, also Markierung öffnen
if next != None:
result.append( "<" )
is_open = True
# Und einen Buchstaben aus unserer Suchanfrage anhängen
result.append( query[:1] )
query = query[1:]
# Wir befinden uns direkt zwischen zwei gefundenen Buchstaben
else:
# Die Markierung ist noch nicht offen,
# wir befinden uns also direkt am Anfang der Zeile
# Wir öffnen sie
if not is_open:
result.append( "<" )
is_open = True
# Wir kopieren einen Buchstaben unserer Suchanfrage...
result.append( query[:1] )
query = query[1:]
# Wir befinden uns am Ende der Zeile, wir müssen
# noch die Markierung schließen
if next == None:
result.append( ">" )
is_open = False
# Ergebnis zusammentun und zurück geben
return "".join( result )
import getopt, sys
def usage():
print "%s [-e] [-s] [-i input-file] query" % sys.argv[0]
def __main__():
# Argumente parsen
try:
opts, args = getopt.getopt( sys.argv[1:], "sei:" )
except getopt.GetoptError, err:
print str( err )
usage()
sys.exit(1)
# Argumente auswerten und zuweisen
case_sensitive = False
extended = False
input_file = "presidents.txt"
for option, value in opts:
if option == '-i':
input_file = value
elif option == "-e":
extended = True
elif option == "-s":
case_sensitive = True
# Gucken ob wir einen Suchbegriff haben
if len( args ) != 1:
usage()
sys.exit(2)
# den Matcher erstellen
matcher = FuzzyMatcher( args[0], case_sensitive )
# Zeile für Zeile durch die Datei gehen
fp = open( input_file, "r" )
for line in fp:
line = line.strip()
# und gefundene Begriffe ausgeben
if matcher.match( line ):
print matcher.highlight( line ) if extended else line
# Ordnung muss ein
fp.close()
if __name__ == "__main__":
__main__()