From 2ae79cfe782c65ee02c796b412a29428370b82ff Mon Sep 17 00:00:00 2001 From: Guenter Milde Date: Tue, 10 Jun 2014 12:22:17 +0200 Subject: [PATCH] Python-Skript Update. Sonderbuchstaben bei Sortierung, Test auf Regelaenderungen als Methode von WordEntry --- skripte/python/abgleich_neueintraege.py | 55 +++++++----- skripte/python/abgleich_sprachvarianten.py | 43 --------- skripte/python/expand_teilwoerter.py | 137 ++++++++++++++--------------- skripte/python/prepare_patch.py | 15 ++-- skripte/python/werkzeug.py | 112 ++++++++++++++++++----- 5 files changed, 197 insertions(+), 165 deletions(-) diff --git a/skripte/python/abgleich_neueintraege.py b/skripte/python/abgleich_neueintraege.py index b9fd360..b198c87 100644 --- a/skripte/python/abgleich_neueintraege.py +++ b/skripte/python/abgleich_neueintraege.py @@ -35,7 +35,10 @@ from expand_teilwoerter import expand_wordfile # neuwortdatei = "spell/zusatz-de-1996-aspell-compact" neuwortdatei = "spell/dehyph-exptl-MV-KorrekturenA-Z.txt" # neuwortdatei = "spell/DDR.txt" -neuwortdatei = 'philo.txt' + +# Vorhandene identische Einträge aus Neueinträgen aussortieren:: + +filtern = False # Funktionen # ----------- @@ -423,7 +426,7 @@ def endungsabgleich(key, alt, neu, grossklein=False): altkey, key, alt, neu, unicode(entry)) return '' - entry.conflate_fields() + entry.regelaenderungen() return entry @@ -494,8 +497,8 @@ endungen = [ (u'-te',u't'), (u'-tern', u't-re'), (u'-ös', u'ö-se'), - (u'a', u'-ar'), - (u'a', u'-as'), + (u'a', u'ar'), + (u'a', u'as'), (u'b', u'-be'), (u'b', u'-ber'), (u'bar', u't'), @@ -511,7 +514,7 @@ endungen = [ (u'd', u'-der'), (u'd', u'-des'), (u'd', u'>heit'), - (u'e', u'-en'), + (u'e', u'en'), (u'e-ren', u'-ti-on'), (u'e-ren', u'sch'), (u'el', u'le'), @@ -666,6 +669,7 @@ def zerlege(s): def trenne_key(key, grossklein = False): entries = [] + sep = u'=' for k1, k2 in zerlege(key): if grossklein: k1 = toggle_case(k1) @@ -693,29 +697,29 @@ def trenne_key(key, grossklein = False): if grossklein: w1 = toggle_case(w1) w2 = w2.lower() - if (u'==' in w1) or (u'==' in w2): - sep = u'===' - elif (u'=' in w1) or (u'=' in w2): - sep = u'==' - else: - sep = u'=' - wort = sep.join([w1, w2]) + level = 1 + while (level*sep in w1) or (level*sep in w2): + level += 1 + wort = (level*sep).join([w1, w2]) entry.append(wort) + entry.conflate_fields() entries.append(entry) return entries + def filter_neuliste(neuwortdatei, words): neue = [] for line in open(neuwortdatei): line = line.decode('utf8').strip() if line.startswith('#'): neue.append(line) - continue + continue neueintrag = WordEntry(line) - if neueintrag != words.get(neueintrag[0]): - neue.append(line) + alteintrag = words.get(neueintrag[0]) + if len(neueintrag) == 1 or neueintrag == alteintrag: + print 'vorhanden:', line else: - print 'Doppeleintrag:', line + neue.append(line) return neue @@ -723,14 +727,15 @@ if __name__ == '__main__': # sys.stdout mit UTF8 encoding. sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) - -# Filtern:: - # words = WordFile('../../wortliste').asdict() - # for line in filter_neuliste(neuwortdatei, words): - # print line - # sys.exit() +# Filtern:: + if filtern: + words = WordFile('../../wortliste').asdict() + for line in filter_neuliste(neuwortdatei, words): + print line + sys.exit() + # `Wortliste` einlesen:: wordfile = WordFile('../../wortliste') @@ -878,9 +883,11 @@ if __name__ == '__main__': identische = {} for entry in newentries: - key = entry[0].lower() - if entry == alle_neuen.get(key): + altentry = alle_neuen.get(entry[0].lower()) + if entry == altentry: identische[key] = entry + elif altentry: + alle_neuen.get(key).comment += u'WL:' + u';'.join(entry[1:]) # Ausgabe:: diff --git a/skripte/python/abgleich_sprachvarianten.py b/skripte/python/abgleich_sprachvarianten.py index 50bf9d9..85b44c4 100755 --- a/skripte/python/abgleich_sprachvarianten.py +++ b/skripte/python/abgleich_sprachvarianten.py @@ -48,49 +48,6 @@ def conflate(wortliste): entry.conflate_fields() continue -# Prüfe ein getrenntes Wort auf Vorkommen von Regeländerungen der -# Orthographiereform 1996. -# Gib eine Eintragszeile zurück. -# -# >>> from abgleich_sprachvarianten import regelaenderungen -# >>> print regelaenderungen(u'Wür-ste') -# Würste;-2-;Wür-ste;Würs-te -# >>> print regelaenderungen(u'Würs-te') -# Würste;-2-;Wür-ste;Würs-te -# >>> print regelaenderungen(u'He-cke') -# Hecke;-2-;He{ck/k-k}e;He-cke -# >>> print regelaenderungen(u'Ligu-ster=he-cke') -# Ligusterhecke;-2-;Ligu-ster=he{ck/k-k}e;Ligus-ter=he-cke -# >>> print regelaenderungen(u'Hass') -# Hass;-2-;-3-;Hass;Hass -# >>> print regelaenderungen(u'fasst') -# fasst;-2-;-3-;fasst;fasst -# -# :: - -def regelaenderungen(wort): - # Regeländerungen: - r1901 = (u'-st', u'{ck/k-k}') - r1996 = (u's-t', u'-ck') - # kein Schluss-ss und sst in de-1901 - # aber: 'ßt' und Schluß-ß auch in de-1996 möglich (langer Vokal) - - w1901, w1996 = wort, wort - for r1, r2 in zip(r1901, r1996): - w1901 = w1901.replace(r2,r1) - w1996 = w1996.replace(r1,r2) - if u'sst' in wort or wort.endswith(u'ss'): - w1901 = None - - if w1901 == w1996: # keine Regeländerung im Wort - line = u'%s;%s' % (join_word(wort), wort) - elif w1901 is None: - line = u'%s;-2-;-3-;%s;%s' % (join_word(wort), w1996, w1996) - else: - line = u'%s;-2-;%s;%s' % (join_word(wort), w1901, w1996) - - return line - if __name__ == '__main__': diff --git a/skripte/python/expand_teilwoerter.py b/skripte/python/expand_teilwoerter.py index 86e0432..faa309b 100644 --- a/skripte/python/expand_teilwoerter.py +++ b/skripte/python/expand_teilwoerter.py @@ -7,12 +7,12 @@ # Erweitern der Wortliste um Kombinationen von Teilwörtern # ======================================================== -# +# # Zerlegen von Composita an den Wortfugen und Übernahme der Teile als # eigenständige Einträge. -# +# # >>> from expand_teilwoerter import * -# +# # :: import os, re, sys, codecs, copy @@ -22,30 +22,30 @@ from werkzeug import (WordFile, WordEntry, join_word, # Funktionen # ----------- -# +# # Iterator, gibt alle geordneten Teilkombinationen zurück -# +# # >>> list(multisplitter(u'test', u'=')) # [u'test'] -# +# # >>> list(multisplitter(u'a=b', u'=')) # [u'a', u'a=b', u'b'] -# +# # >>> list(multisplitter(u'a=b=c', u'=')) # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c'] -# +# # >>> list(multisplitter('a=b=c=d', '=')) # ['a', 'a=b', 'a=b=c', 'a=b=c=d', 'b', 'b=c', 'b=c=d', 'c', 'c=d', 'd'] -# +# # >>> list(multisplitter(u'a=b==c', u'==')) # [u'a=b', u'a=b==c', u'c'] -# +# # >>> list(multisplitter('a=b==c=de', '==')) # ['a=b', 'a=b==c=de', 'c=de'] -# +# # >>> list(multisplitter('a=b==c=de', '===')) # ['a=b==c=de'] -# +# # >>> list(multisplitter('er[>> list(multisplitter('Schiff[=s/s=]tau', u'=')) @@ -54,7 +54,7 @@ from werkzeug import (WordFile, WordEntry, join_word, # [u'a{ll/ll=l}ie-bend'] # >>> list(multisplitter('Be[t=t/{tt/tt=t}]uch', u'=')) # [u'Be[t=t/{tt/tt=t}]uch'] -# +# # :: def multisplitter(wort, sep): @@ -72,24 +72,24 @@ def multisplitter(wort, sep): # Gib eine Liste möglicher Zerlegungen eines Kompositums zurück. -# Berücksichtige dabei die Bindungsstärke bis zum Level 3 +# Berücksichtige dabei die Bindungsstärke bis zum Level 3 # ("===", zur Zeit höchste Auszeichnung in der Wortliste). -# +# # >>> multisplit(u'test') # [u'test'] -# +# # >>> multisplit(u'a=b') # [u'a', u'a=b', u'b'] -# +# # >>> multisplit(u'a=b=c') # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c'] -# +# # >>> multisplit(u'a==b=c') # [u'a', u'a==b=c', u'b', u'b=c', u'c'] -# +# # >>> multisplit(u'a==b=c==d') # [u'a', u'a==b=c', u'a==b=c==d', u'b', u'b=c', u'c', u'b=c==d', u'd'] -# +# # >>> for w in multisplit(u'Brenn=stoff==zel-len===an>> aalbestand = WordEntry(u'Aalbestand;Aal=be>> split_entry(aalbestand) # [[u'Aal', u'Aal'], [u'Aalbestand', u'Aal=be>> godi = WordEntry(u'Abendgottesdienste;-2-;Abend==got-tes=dien-ste;Abend==got-tes=diens-te') # >>> for entry in split_entry(godi): # ... print entry @@ -138,14 +138,14 @@ def multisplit(wort): # Gottes;-2-;Got-tes;Got-tes # Gottesdienste;-2-;Got-tes=dien-ste;Got-tes=diens-te # Dienste;-2-;Dien-ste;Diens-te -# +# # >>> bb = WordEntry(u'Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch') # >>> for entry in split_entry(bb): # ... print entry # Biber;-2-;Bi-ber # Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch # Bettuch;-2-;Be[t=t/{tt/tt=t}]uch -# +# # :: def split_entry(entry): @@ -157,7 +157,7 @@ def split_entry(entry): if u'=' not in wort: continue # nichts zu splitten parts = multisplit(wort) - + # Kopien des Originaleintrags erstellen if not entries: for part in parts: @@ -166,7 +166,7 @@ def split_entry(entry): # Entries ausfüllen for i in range(len(parts)): entries[i][col] = parts[i] - + if entries: for e in entries: e.conflate_fields() # Sprachabgleich @@ -178,7 +178,7 @@ def split_entry(entry): def expand_wordfile(wordfile): words = {} # Wörter aus der Liste - + for entry in wordfile: try: entries = split_entry(entry) @@ -186,12 +186,14 @@ def expand_wordfile(wordfile): # print "problematisch", unicode(entry) words[entry[0]] = entry continue - + for e in entries: - if len(entries) == 1 or ( - e[0].lower() not in words and e[0].title() not in words): + if (len(entries) == 1 + or (e[0].lower() not in words and e[0].title() not in words) + or len(e[0]) <= 3 and len(e) == 2 # kurze einfache Wörter + ): words[e[0]] = e - + return words def exists(wort): @@ -207,46 +209,41 @@ if __name__ == '__main__': wordfile = WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen - # Wichtung: - sprachvariante = 'de-1996' - sprachvariante = 'de-1901' - words = wordfile.asdict() - for entry in words.itervalues(): - wort = entry.get(sprachvariante) - if not wort: - continue - if (u'<=' in wort or u'=>' in wort or u'==' in wort): - continue - parts = [part for part in multisplit(wort) - if u'=' not in part] - if len(parts) == 3: - if parts[1] == u'zu': - continue - if (exists(parts[0]) and exists(''.join(parts[1:])) - and not(exists(parts[-1]) - and (exists(''.join(parts[:-1])) or exists(''.join(parts[:-1])+u's'))) - ): - for i in range(1,len(parts)): - parts[i] = parts[i].lower() - wort = u'=='.join([parts[0], u'='.join(parts[1:])]) - entry.set(wort, sprachvariante) - sprachabgleich(entry) - print unicode(entry) - - sys.exit() - -if __name__ == '__main__': - - # sys.stdout mit UTF8 encoding. - sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) +# Wichtung:: + + # sprachvariante = 'de-1996' + # sprachvariante = 'de-1901' + # words = wordfile.asdict() + # for entry in words.itervalues(): + # wort = entry.get(sprachvariante) + # if not wort: + # continue + # if (u'<=' in wort or u'=>' in wort or u'==' in wort): + # continue + # parts = [part for part in multisplit(wort) + # if u'=' not in part] + # if len(parts) == 3: + # if parts[1] == u'zu': + # continue + # if (exists(parts[0]) and exists(''.join(parts[1:])) + # and not(exists(parts[-1]) + # and (exists(''.join(parts[:-1])) or exists(''.join(parts[:-1])+u's'))) + # ): + # for i in range(1,len(parts)): + # parts[i] = parts[i].lower() + # wort = u'=='.join([parts[0], u'='.join(parts[1:])]) + # entry.set(wort, sprachvariante) + # sprachabgleich(entry) + # print unicode(entry) + # + # sys.exit() + +# expandieren und Speichern:: -# `Wortliste` einlesen:: - - wordfile = WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen words = expand_wordfile(wordfile) print len(words), "expandiert" - + outfile = open('wortliste-expandiert', 'w') for entry in sorted(words.values(), key=sortkey_duden): diff --git a/skripte/python/prepare_patch.py b/skripte/python/prepare_patch.py index 3e80e3b..8cea000 100755 --- a/skripte/python/prepare_patch.py +++ b/skripte/python/prepare_patch.py @@ -34,7 +34,6 @@ from copy import copy, deepcopy from werkzeug import WordFile, WordEntry, join_word, udiff, sortkey_duden -from abgleich_sprachvarianten import regelaenderungen def teste_datei(datei): """Teste, ob Datei geöffnet werden kann.""" @@ -327,18 +326,20 @@ def neu(wordfile, datei): if not line: continue # Eintrag ggf. komplettieren: - if u';' in line: - key = line.split(u';')[0] - else: # getrenntes Wort - line = regelaenderungen(line) + if u';' not in line: + line = u's%;s%' % (join_word(line), line) + entry = WordEntry(line) + key = entry[0] # Test auf "Neuwert": if key in words: print key.encode('utf8'), 'schon vorhanden' continue if key.lower() in words or key.title() in words: - print key.encode('utf8'), 'mit anderer Groß-/Kleinschreibung vorhanden' + print key.encode('utf8'), 'mit anderer Großschreibung vorhanden' continue - wortliste_neu.append(WordEntry(line)) + + entry.regelaenderungen() # teste auf Dinge wie s-t/-st + wortliste_neu.append(entry) words.add(key) # Sortieren diff --git a/skripte/python/werkzeug.py b/skripte/python/werkzeug.py index c2078e0..da5dd29 100755 --- a/skripte/python/werkzeug.py +++ b/skripte/python/werkzeug.py @@ -115,7 +115,7 @@ class WordEntry(list): # # Kommentare (aktualisiert, wenn Kommentar vorhanden):: - comment = None + comment = u'' # Feldbelegung: # @@ -183,7 +183,7 @@ class WordEntry(list): def __unicode__(self): line = ';'.join(self) - if self.comment is not None: + if self.comment: line += ' #' + self.comment return line @@ -355,6 +355,68 @@ class WordEntry(list): self.pop() +# Prüfe auf Vorkommen von Regeländerungen der Orthographiereform 1996. +# +# >>> entry = WordEntry(u'Würste;Wür-ste') +# >>> entry.regelaenderungen() +# >>> print unicode(entry) +# Würste;-2-;Wür-ste;Würs-te +# >>> entry = WordEntry(u'Würste;Würs-te') +# >>> entry.regelaenderungen() +# >>> print unicode(entry) +# Würste;-2-;Wür-ste;Würs-te +# >>> entry = WordEntry(u'Hecke;He-cke') +# >>> entry.regelaenderungen() +# >>> print unicode(entry) +# Hecke;-2-;He{ck/k-k}e;He-cke +# >>> entry = WordEntry(u'Ligusterhecke;Ligu-ster=he{ck/k-k}e') +# >>> entry.regelaenderungen() +# >>> print unicode(entry) +# Ligusterhecke;-2-;Ligu-ster=he{ck/k-k}e;Ligus-ter=he-cke +# >>> entry = WordEntry(u'Hass;Hass') +# >>> entry.regelaenderungen() +# >>> print unicode(entry) +# Hass;-2-;-3-;Hass;Hass +# >>> entry = WordEntry(u'fasst;fasst') +# >>> entry.regelaenderungen() +# >>> print unicode(entry) +# fasst;-2-;-3-;fasst;fasst +# +# :: + + def regelaenderungen(self): + # Regeländerungen: + r1901 = (u'-st', u'{ck/k-k}') + r1996 = (u's-t', u'-ck') + # kein Schluss-ss und sst in de-1901 + # aber: 'ßt' und Schluß-ß auch in de-1996 möglich (langer Vokal) + + w1901 = self.get('de-1901') + w1996 = self.get('de-1996') + + for r1, r2 in zip(r1901, r1996): + w1901 = w1901.replace(r2,r1) + w1996 = w1996.replace(r1,r2) + if u'sst' in w1901 or w1901.endswith(u'ss'): + w1901 = None + + if w1901 == w1996: # keine Regeländerung im Wort + if len(self) > 2: + self.conflate_fields() + return + elif w1901 is None: + self.extend( ['']*(5-len(self)) ) + self[1] = u'-2-' + self[2] = u'-3-' + self[3] = w1996 + self[4] = w1996 + else: + self.extend( ['']*(4-len(self)) ) + self[1] = u'-2-' + self[2] = w1901 + self[3] = w1996 + + # Funktionen # ========== @@ -731,25 +793,32 @@ def toggle_case(wort): # >>> print ', '.join(e[0] for e in s) # Abflussrohren, Abflußrohren, Abflußröhren # -# Umlautumschreibung: +# Umschreibung # -# :: +# Ligaturen auflösen und andere "normalisierunde" Ersetzungen für den +# (Haupt-)Sortierschlüssel (Akzente werden über ``unicodedata.normalize`` +# entfernt):: + +umschrift_skey = { + ord(u'æ'): u'ae', + ord(u'œ'): u'oe', + ord(u'ſ'): u's', + } + +# "Zweitschlüssel" zur Unterscheidung von Umlauten/SZ und Basisbuchstaben:: + +umschrift_subkey = { + ord(u'a'): u'a*', + ord(u'å'): u'aa', + ord(u'ä'): u'ae', + ord(u'o'): u'o*', + ord(u'ö'): u'oe', + ord(u'ø'): u'oe', + ord(u'u'): u'u*', + ord(u'ü'): u'ue', + ord(u'ß'): u'sz', + } -umschrift = { - ord(u'A'): u'A*', - ord(u'Ä'): u'Ae', - ord(u'O'): u'O*', - ord(u'Ö'): u'Oe', - ord(u'U'): u'U*', - ord(u'Ü'): u'Ue', - ord(u'a'): u'a*', - ord(u'ä'): u'ae', - ord(u'o'): u'o*', - ord(u'ö'): u'oe', - ord(u'u'): u'u*', - ord(u'ü'): u'ue', - ord(u'ß'): u'sz', - } # sortkey_duden # ------------- @@ -785,6 +854,7 @@ def sortkey_duden(entry): # Akzent als "Grundzeichen + kombinierender Akzent". Anschließend alle # nicht-ASCII-Zeichen ignorieren:: + skey = skey.translate(umschrift_skey) skey = unicodedata.normalize('NFKD', skey) skey = unicode(skey.encode('ascii', 'ignore')) @@ -797,8 +867,8 @@ def sortkey_duden(entry): # :: if key != skey: - subkey = key.translate(umschrift) - skey = u' '.join([skey,subkey]) + subkey = key.translate(umschrift_subkey) + skey = u'%s %s' % (skey,subkey) # Gib den Sortierschlüssel zurück:: -- 2.11.4.GIT